📄 task.h
字号:
//-< TASK.H >--------------------------------------------------------*--------*
// SAL Version 1.0 (c) 1997 GARRET * ? *
// (System Abstraction Layer) * /\| *
// * / \ *
// Created: 7-Jan-97 K.A. Knizhnik * / [] \ *
// Last update: 23-Apr-97 K.A. Knizhnik * GARRET *
//-------------------------------------------------------------------*--------*
// Mutitasking and syncronization mechanisms abstractions
//-------------------------------------------------------------------*--------*
#ifndef __TASK_H__
#define __TASK_H__
#include "stdtp.h"
typedef unsigned timeout_t; // timeout in milliseconds
#ifdef _WIN32
#include "wtask.h"
#else
#if defined PTHREADS || defined LINUX
#include "ptask.h"
#else
#include "ctask.h"
#endif
#endif
namespace sal {
//
// Mutual exclusion: only one task can hold mutex at the same time.
// Task holding mutex can call 'enter' any number of times and
// will hold mutex until correspondent number of 'leave' will be
// executed. If task holding mutex is terminated mutex is automaticaly unlocked
//
class mutex : private mutex_internals {
friend class eventex;
friend class semaphorex;
public:
void enter() { mutex_internals::enter(); }
void leave() { mutex_internals::leave(); }
};
//
// Critical section. When object of this class is used as local
// variable, mutex is locked by constructor at the beginning of the block
// (entering critical section) and unlocked by destructor after existing from
// the block (leaving critical section)
//
class critical_section {
mutex& cs;
public:
critical_section(mutex& guard) : cs(guard) {
cs.enter();
}
~critical_section() { cs.leave(); }
};
//
// Standard sempaphore supporting wait (P) and signal (V) operations.
//
class semaphore : private semaphore_internals {
public:
//
// Wait semaphore to be signaled
//
void wait() { semaphore_internals::wait(); }
//
// Wait for signal for a specified period of time.
// If timeout expired before semaphore is signaled then 'False'
// is returned.
//
boolean wait_with_timeout(timeout_t msec) {
return semaphore_internals::wait_with_timeout(msec);
}
//
// Wakeup one task waiting for semaphore. If no task is waiting
// then value of semaphore is increased so that following wait will
// not block the task.
//
void signal() { semaphore_internals::signal(); }
semaphore(int init_count = 0) : semaphore_internals(init_count) {}
};
//
// Semaphore with associated mutex
//
class semaphorex : private semaphorex_internals {
public:
//
// Wait semaphore to be signaled. Should be called with associated mutex
// locked. Before wait mutex is unlocked and will locked again before
// returning.
//
void wait() { semaphorex_internals::wait(); }
//
// Wait for signal for a specified period of time.
// If timeout expired before semaphore is signaled then 'False'
// is returned. Should be called with associated mutex
// locked. Before wait mutex is unlocked and will locked again before
// returning.
//
boolean wait_with_timeout(timeout_t msec) {
return semaphorex_internals::wait_with_timeout(msec);
}
//
// Wakeup one task waiting for semaphore. If no task is waiting
// then value of semaphore is increased so that following wait will
// not block the task. Should be called with associated mutex locked.
//
void signal() { semaphorex_internals::signal(); }
semaphorex(mutex& cs, int init_count = 0)
: semaphorex_internals(cs, init_count) {}
};
//
// Event with manual reset
//
class event : private event_internals {
public:
//
// Wait event to be signaled
//
void wait() { event_internals::wait(); }
//
// Wait for signal for a specified period of time.
// If timeout expired before event is signaled then 'False' is returned.
//
boolean wait_with_timeout(timeout_t msec) {
return event_internals::wait_with_timeout(msec);
}
//
// Switch event object to signaled state
//
void signal() { event_internals::signal(); }
//
// Reset event to non-signaled state.
//
void reset() { event_internals::reset(); }
event(boolean signaled = False) : event_internals(signaled) {}
};
//
// Event with associated mutex
//
class eventex : private eventex_internals {
public:
//
// Wait event to be signaled. Associated mutex is released before wait
// and will be relocked before returning.
//
void wait() { eventex_internals::wait(); }
//
// Wait for signal for a specified period of time. Associated mutex
// is released before wait and will be relocked before returning.
// If timeout expired before event is signaled then 'False' is returned.
//
boolean wait_with_timeout(timeout_t msec) {
return eventex_internals::wait_with_timeout(msec);
}
//
// Switch event object to signaled state. Should be called with associated
// mutex locked.
//
void signal() { eventex_internals::signal(); }
//
// Reset event to non-signaled state. Should be called with associated
// mutex locked.
//
void reset() { eventex_internals::reset(); }
eventex(mutex& cs, boolean signaled = False)
: eventex_internals(cs, signaled) {}
};
//
// Task is a unit for scheduling excution. Schedulig can be either preemptive
// or cooperative. After task termination all mutexes hold by this task
// will be released
//
class task : private task_internals {
friend class task_internals;
public:
typedef void (task_proc *fptr)(void* arg);
enum priority {
pri_background,
pri_low,
pri_normal,
pri_high,
pri_realtime
};
enum {
min_stack = 8*1024,
small_stack = 16*1024,
normal_stack = 64*1024,
big_stack = 256*1024,
huge_stack = 1024*1024
};
//
// Create new task. Pointer to task object returned by this function
// can be used only for thread identification.
//
static task* create(fptr f, void* arg = NULL, priority pri = pri_normal,
size_t stack_size = normal_stack);
//
// Initialize tasking.
//
static void initialize(size_t main_stack_size = normal_stack);
//
// Forse task rescheduling
//
static void reschedule();
//
// Terminate current task
//
static void exit();
//
// Current task will sleep during specified period
//
static void sleep(timeout_t msec);
//
// Get current task
//
static task* current();
//void* get_arg () { return arg; }
};
template<class T>
class fifo_queue {
protected:
struct queue_end {
semaphorex sem;
volatile size_t pos;
volatile boolean wait_flag;
queue_end(mutex& cs) : sem(cs) { pos = 0; wait_flag = False; }
};
mutex cs;
queue_end put, get;
T* buf;
const size_t buf_size;
public:
boolean is_empty() const { return put.pos == get.pos; }
boolean is_full() const {
return put.pos == get.pos-1
|| (get.pos == 0 && put.pos == buf_size-1);
}
fifo_queue& operator << (T const& elem) {
cs.enter();
put.wait_flag = True;
while (is_full()) {
put.sem.wait();
}
put.wait_flag = False;
buf[put.pos] = elem;
if (++put.pos == buf_size) put.pos = 0;
if (get.wait_flag) {
get.sem.signal();
}
cs.leave();
return *this;
}
fifo_queue& operator >> (T& elem) {
cs.enter();
get.wait_flag = True;
while (is_empty()) {
get.sem.wait();
}
get.wait_flag = False;
elem = buf[get.pos];
if (++get.pos == buf_size) get.pos = 0;
if (put.wait_flag) {
put.sem.signal();
}
cs.leave();
return *this;
}
fifo_queue(size_t size) : put(cs), get(cs), buf_size(size) {
buf = new T[size];
}
~fifo_queue() { delete[] buf; }
};
class barrier {
protected:
mutex cs;
eventex e;
int count;
public:
void reset(int n) {
count = n;
e.reset();
}
void reach() {
cs.enter();
assert(count > 0);
if (--count != 0) {
e.wait();
} else {
e.signal();
}
cs.leave();
}
barrier() : e(cs) { count = 0; }
};
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -