cwidget 0.5.16
|
00001 // channel.h -*-c++-*- 00002 // 00003 // Copyright (C) 2005, 2007 Daniel Burrows 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License as 00007 // published by the Free Software Foundation; either version 2 of 00008 // the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; see the file COPYING. If not, write to 00017 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 // Boston, MA 02111-1307, USA. 00019 00020 #ifndef EVENT_QUEUE_H 00021 #define EVENT_QUEUE_H 00022 00023 #include "threads.h" 00024 00025 #include <deque> 00026 00027 namespace cwidget 00028 { 00029 namespace threads 00030 { 00045 template<typename T> 00046 class event_queue 00047 { 00048 std::deque<T> q; 00049 00050 condition c; 00051 mutable mutex m; 00052 00053 struct not_empty 00054 { 00055 const std::deque<T> &q; 00056 public: 00057 not_empty(const std::deque<T> &_q) 00058 :q(_q) 00059 { 00060 } 00061 00062 bool operator()() const 00063 { 00064 return !q.empty(); 00065 } 00066 }; 00067 00068 event_queue(const event_queue &other); 00069 event_queue &operator=(const event_queue &other); 00070 public: 00072 event_queue() 00073 { 00074 } 00075 00076 ~event_queue() 00077 { 00078 } 00079 00081 void put(const T &t) 00082 { 00083 mutex::lock l(m); 00084 00085 q.push_back(t); 00086 c.wake_one(); 00087 } 00088 00090 T get() 00091 { 00092 mutex::lock l(m); 00093 00094 c.wait(l, not_empty(q)); 00095 T rval = q.front(); 00096 q.pop_front(); 00097 00098 return rval; 00099 } 00100 00107 bool try_get(T &out) 00108 { 00109 mutex::lock l(m); 00110 00111 if(q.empty()) 00112 return false; 00113 else 00114 { 00115 out = q.front(); 00116 q.pop_front(); 00117 return true; 00118 } 00119 } 00120 00124 bool timed_get(T &out, const timespec &until) 00125 { 00126 mutex::lock l(m); 00127 00128 if(c.timed_wait(l, until, not_empty(q))) 00129 { 00130 out = q.front(); 00131 q.pop_front(); 00132 return true; 00133 } 00134 else 00135 return false; 00136 } 00137 00139 bool empty() const 00140 { 00141 // Not sure the lock is required here, but it makes things a bit 00142 // safer in case the STL is thread-unsafe in weird ways. 00143 mutex::lock l(m); 00144 bool rval = q.empty(); 00145 return rval; 00146 } 00147 }; 00148 } 00149 } 00150 00151 #endif