1
/* $Id: os.hpp 2394 2008-12-23 17:27:53Z bennylp $ */
3
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#ifndef __PJPP_OS_HPP__
21
#define __PJPP_OS_HPP__
24
#include <pj/string.h>
25
#include <pj++/types.hpp>
26
#include <pj++/pool.hpp>
39
static pj_status_t create( Pj_Pool *pool, pj_thread_t **thread,
40
pj_thread_proc *proc, void *arg,
42
const char *name = NULL,
43
pj_size_t stack_size = 0 )
45
return pj_thread_create(pool->pool_(), name, proc, arg, stack_size,
52
static pj_status_t register_this_thread( pj_thread_desc desc,
54
const char *name = NULL )
56
return pj_thread_register( name, desc, thread );
60
// Get current thread.
61
// Will return pj_thread_t (sorry folks, not Pj_Thread).
63
static pj_thread_t *this_thread()
65
return pj_thread_this();
71
static const char *get_name(pj_thread_t *thread)
73
return pj_thread_get_name(thread);
79
static pj_status_t resume(pj_thread_t *thread)
81
return pj_thread_resume(thread);
87
static pj_status_t sleep(unsigned msec)
89
return pj_thread_sleep(msec);
93
// Join the specified thread.
95
static pj_status_t join(pj_thread_t *thread)
97
return pj_thread_join(thread);
103
static pj_status_t destroy(pj_thread_t *thread)
105
return pj_thread_destroy(thread);
115
// Derive a class from this class, then override main().
117
class Pj_Thread : public Pj_Object
122
FLAG_SUSPENDED = PJ_THREAD_SUSPENDED
126
// Default constructor.
142
// This is the main thread function.
144
virtual int main() = 0;
149
pj_status_t create( Pj_Pool *pool,
151
const char *thread_name = NULL,
152
pj_size_t stack_size = PJ_THREAD_DEFAULT_STACK_SIZE)
155
return Pj_Thread_API::create( pool, &thread_, &thread_proc, this,
156
flags, thread_name, stack_size);
160
// Get pjlib compatible thread object.
162
pj_thread_t *pj_thread_t_()
170
const char *get_name()
172
return Pj_Thread_API::get_name(thread_);
176
// Resume a suspended thread.
180
return Pj_Thread_API::resume(thread_);
188
return Pj_Thread_API::join(thread_);
194
pj_status_t destroy()
197
Pj_Thread_API::destroy(thread_);
203
pj_thread_t *thread_;
205
static int PJ_THREAD_FUNC thread_proc(void *obj)
207
Pj_Thread *thread_class = (Pj_Thread*)obj;
208
return thread_class->main();
215
// (threads that were started by external means, i.e. not
216
// with Pj_Thread::create).
218
// This class will normally be defined as local variable in
219
// external thread's stack, normally inside thread's main proc.
220
// But be aware that the handle will be destroyed on destructor!
222
class Pj_External_Thread : public Pj_Thread
230
// Register external thread so that pjlib functions can work
233
pj_status_t register_this_thread( const char *name=NULL )
235
return Pj_Thread_API::register_this_thread(desc_, &thread_,name);
239
pj_thread_desc desc_;
244
// Thread specific data/thread local storage/TLS.
246
class Pj_Thread_Local_API
250
// Allocate thread local storage (TLS) index.
252
static pj_status_t alloc(long *index)
254
return pj_thread_local_alloc(index);
260
static void free(long index)
262
pj_thread_local_free(index);
266
// Set thread specific data.
268
static pj_status_t set(long index, void *value)
270
return pj_thread_local_set(index, value);
274
// Get thread specific data.
276
static void *get(long index)
278
return pj_thread_local_get(index);
287
// Pj_Atomic_Var var(pool, 0);
290
class Pj_Atomic_Var : public Pj_Object
294
// Default constructor, initialize variable with NULL.
302
// Construct atomic variable.
304
Pj_Atomic_Var(Pj_Pool *pool, pj_atomic_value_t value)
319
// Create atomic variable.
321
pj_status_t create( Pj_Pool *pool, pj_atomic_value_t value)
324
return pj_atomic_create(pool->pool_(), value, &var_);
333
pj_atomic_destroy(var_);
339
// Get pjlib compatible atomic variable.
341
pj_atomic_t *pj_atomic_t_()
349
void set(pj_atomic_value_t val)
351
pj_atomic_set(var_, val);
357
pj_atomic_value_t get()
359
return pj_atomic_get(var_);
371
// Increment and get the result.
373
pj_atomic_value_t inc_and_get()
375
return pj_atomic_inc_and_get(var_);
387
// Decrement and get the result.
389
pj_atomic_value_t dec_and_get()
391
return pj_atomic_dec_and_get(var_);
397
void add(pj_atomic_value_t value)
399
pj_atomic_add(var_, value);
403
// Add the variable and get the value.
405
pj_atomic_value_t add_and_get(pj_atomic_value_t value)
407
return pj_atomic_add_and_get(var_, value );
418
class Pj_Mutex : public Pj_Object
426
DEFAULT = PJ_MUTEX_DEFAULT,
427
SIMPLE = PJ_MUTEX_SIMPLE,
428
RECURSE = PJ_MUTEX_RECURSE,
432
// Default constructor will create default mutex.
434
explicit Pj_Mutex(Pj_Pool *pool, Type type = DEFAULT,
435
const char *name = NULL)
438
create(pool, type, name);
452
pj_status_t create( Pj_Pool *pool, Type type, const char *name = NULL)
455
return pj_mutex_create( pool->pool_(), name, type,
460
// Create simple mutex.
462
pj_status_t create_simple( Pj_Pool *pool,const char *name = NULL)
464
return create(pool, SIMPLE, name);
468
// Create recursive mutex.
470
pj_status_t create_recursive( Pj_Pool *pool, const char *name = NULL )
472
return create(pool, RECURSE, name);
476
// Get pjlib compatible mutex object.
478
pj_mutex_t *pj_mutex_t_()
489
pj_mutex_destroy(mutex_);
497
pj_status_t acquire()
499
return pj_mutex_lock(mutex_);
505
pj_status_t release()
507
return pj_mutex_unlock(mutex_);
511
// Try locking the mutex.
513
pj_status_t tryacquire()
515
return pj_mutex_trylock(mutex_);
526
class Pj_Semaphore : public Pj_Object
530
// Construct semaphore
532
Pj_Semaphore(Pj_Pool *pool, unsigned max,
533
unsigned initial = 0, const char *name = NULL)
536
create(pool, max, initial, name);
550
pj_status_t create( Pj_Pool *pool, unsigned max,
551
unsigned initial = 0, const char *name = NULL )
554
return pj_sem_create( pool->pool_(), name, initial, max, &sem_);
558
// Destroy semaphore.
563
pj_sem_destroy(sem_);
569
// Get pjlib compatible semaphore object.
571
pj_sem_t *pj_sem_t_()
573
return (pj_sem_t*)this;
581
return pj_sem_wait(this->pj_sem_t_());
587
pj_status_t acquire()
593
// Try wait semaphore.
595
pj_status_t trywait()
597
return pj_sem_trywait(this->pj_sem_t_());
601
// Try wait semaphore.
603
pj_status_t tryacquire()
613
return pj_sem_post(this->pj_sem_t_());
619
pj_status_t release()
636
// Construct event object.
638
Pj_Event( Pj_Pool *pool, bool manual_reset = false,
639
bool initial = false, const char *name = NULL )
642
create(pool, manual_reset, initial, name);
654
// Create event object.
656
pj_status_t create( Pj_Pool *pool, bool manual_reset = false,
657
bool initial = false, const char *name = NULL)
660
return pj_event_create(pool->pool_(), name, manual_reset, initial,
665
// Get pjlib compatible event object.
667
pj_event_t *pj_event_t_()
673
// Destroy event object.
678
pj_event_destroy(event_);
688
return pj_event_wait(event_);
694
pj_status_t trywait()
696
return pj_event_trywait(event_);
700
// Set event state to signalled.
704
return pj_event_set(this->pj_event_t_());
708
// Release one waiting thread.
712
return pj_event_pulse(this->pj_event_t_());
716
// Set a non-signalled.
720
return pj_event_reset(this->pj_event_t_());
733
pj_status_t get_timestamp()
735
return pj_get_timestamp(&ts_);
738
Pj_Timestamp& operator += (const Pj_Timestamp &rhs)
740
pj_add_timestamp(&ts_, &rhs.ts_);
744
Pj_Timestamp& operator -= (const Pj_Timestamp &rhs)
746
pj_sub_timestamp(&ts_, &rhs.ts_);
750
Pj_Time_Val to_time() const
753
pj_memset(&zero, 0, sizeof(zero));
754
return Pj_Time_Val(pj_elapsed_time(&zero.ts_, &ts_));
757
pj_uint32_t to_msec() const
760
pj_memset(&zero, 0, sizeof(zero));
761
return pj_elapsed_msec(&zero.ts_, &ts_);
764
pj_uint32_t to_usec() const
767
pj_memset(&zero, 0, sizeof(zero));
768
return pj_elapsed_usec(&zero.ts_, &ts_);
771
pj_uint32_t to_nanosec() const
774
pj_memset(&zero, 0, sizeof(zero));
775
return pj_elapsed_nanosec(&zero.ts_, &ts_);
778
pj_uint32_t to_cycle() const
781
pj_memset(&zero, 0, sizeof(zero));
782
return pj_elapsed_cycle(&zero.ts_, &ts_);
799
static pj_status_t gettimeofday( Pj_Time_Val *tv )
801
return pj_gettimeofday(tv);
805
// Parse to time of day.
807
static pj_status_t time_decode( const Pj_Time_Val *tv,
810
return pj_time_decode(tv, pt);
814
// Parse from time of day.
816
static pj_status_t time_encode( const pj_parsed_time *pt,
819
return pj_time_encode(pt, tv);
825
static pj_status_t time_local_to_gmt( Pj_Time_Val *tv )
827
return pj_time_local_to_gmt( tv );
831
// Convert time to local.
833
static pj_status_t time_gmt_to_local( Pj_Time_Val *tv)
835
return pj_time_gmt_to_local( tv );
842
inline pj_status_t Pj_Time_Val::gettimeofday()
844
return Pj_OS_API::gettimeofday(this);
847
inline pj_parsed_time Pj_Time_Val::decode()
850
Pj_OS_API::time_decode(this, &pt);
854
inline pj_status_t Pj_Time_Val::encode(const pj_parsed_time *pt)
856
return Pj_OS_API::time_encode(pt, this);
859
inline pj_status_t Pj_Time_Val::to_gmt()
861
return Pj_OS_API::time_local_to_gmt(this);
864
inline pj_status_t Pj_Time_Val::to_local()
866
return Pj_OS_API::time_gmt_to_local(this);
869
#endif /* __PJPP_OS_HPP__ */