/usr/include/shevek/closure.hh is in libshevek-dev 1.4-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | /* closure.hh - Cooperative multitasking
* Copyright 2008 Bas Wijnen <wijnen@debian.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SHEVEK_CLOSURE_HH
#define SHEVEK_CLOSURE_HH
#include <pthread.h>
#include "refbase.hh"
namespace shevek
{
/// Block and resume without blocking the main loop.
/** Closures allow blocking and resuming the main loop. They
* are implemented with threads, which means that they don't
* work well with multi-threaded programs.
*
* If a function wants to be able to block using a closure, it must be
* called using closure(). It (or any function it calls) can then
* suspend by calling closure::block(). It can be awoken again by
* calling closure::wake() on the closure object.
*/
class closure : public refbase
{
static closure *current;
enum state_t { EMPTY, BLOCKING, RUNNING } state;
sigc::slot0 <void> callback, function;
pthread_t thread;
int blocking_pipe[2];
int waking_pipe[2];
void do_write (int *fds);
void do_read (int *fds);
static void *start_wrapper (void *me);
closure ();
public:
/// Create a new closure.
/** Create a new closure. It will be empty initially.
*/
static Glib::RefPtr <closure> create ()
{ return Glib::RefPtr <closure> (new closure ()); }
/// Check if the closure is empty.
/** Check if the closure is empty. If it is, set_function()
* can be called.
*/
bool empty () const { return state == EMPTY; }
/// Set running function on an empty closure.
/** Set running function. The closure must be empty when this
* is called. When the function exits, the closure returns to
* the empty state, and the callback is called, if given.
*/
void set_function (sigc::slot0 <void> func, bool run = true,
sigc::slot0 <void> cb = sigc::slot0 <void> ());
/// Destructor.
~closure ();
/// Sleep, returning control to the caller until awoken.
/** This function puts the current closure to sleep. It will
* continue to run when awoken with wake(). It can also be
* destroyed. This function uses a global variable to know
* which is the current closure, so it can be called without an
* object, as closure::block (); .
*/
static void block ();
/// Continue running the closure.
/** Wake a closure. It is an error to wake a closure which
* isn't blocking (in particular also the currently running
* closure).
*/
void wake ();
};
}
#endif
|