Pteros  2.0
Molecular modeling library for human beings!
message_channel.h
1 /*
2  *
3  * This source code is part of
4  * ******************
5  * *** Pteros ***
6  * ******************
7  * molecular modeling library
8  *
9  * Copyright (c) 2009-2017, Semen Yesylevskyy
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of Artistic License:
13  *
14  * Please note, that Artistic License is slightly more restrictive
15  * then GPL license in terms of distributing the modified versions
16  * of this software (they should be approved first).
17  * Read http://www.opensource.org/licenses/artistic-license-2.0.php
18  * for details. Such license fits scientific software better then
19  * GPL because it prevents the distribution of bugged derivatives.
20  *
21 */
22 
23 
24 #pragma once
25 
26 #include <mutex>
27 #include <condition_variable>
28 #include <queue>
29 #include <functional>
30 
31 template<class T>
32 class MessageChannel {
33 public:
34  MessageChannel(): buffer_size(10), stop_requested(false) { }
35 
36  MessageChannel(int sz): buffer_size(sz), stop_requested(false) { }
37 
38  void set_buffer_size(int sz){
39  std::lock_guard<std::mutex> lock(mutex);
40  buffer_size = sz;
41  cond.notify_all();
42  }
43 
44  void send_stop(){
45  std::lock_guard<std::mutex> lock(mutex);
46  stop_requested = true;
47  cond.notify_all();
48  }
49 
50  bool empty(){
51  std::lock_guard<std::mutex> lock(mutex);
52  return queue.empty();
53  }
54 
55  bool send(T const& data){
56  std::unique_lock<std::mutex> lock(mutex);
57 
58  // Wait until buffer will clear a bit or until stop is requested
59  cond.wait(lock, [this]{return (queue.size()<buffer_size || stop_requested);} );
60 
61  // If stop requested just do nothing
62  if(stop_requested) return false;
63 
64  queue.push(data);
65  cond.notify_one();
66  return true;
67  }
68 
69  bool recieve(T& popped_value){
70  std::unique_lock<std::mutex> lock(mutex);
71 
72  // Wait until something appears in the queue or until stop requested
73  cond.wait(lock, [this]{return (!queue.empty() || stop_requested);} );
74 
75  // If stop requested see if there is something in, if not return false
76  if(stop_requested && queue.empty()) return false;
77 
78  popped_value = queue.front();
79  queue.pop();
80  cond.notify_all();
81  return true;
82  }
83 
84 private:
85  int buffer_size;
86  std::condition_variable cond;
87  std::mutex mutex;
88  std::queue<T> queue;
89  bool stop_requested;
90 };