cwidget  0.5.16
event_queue.h
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