os.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. /*
  2. * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #ifndef __PJPP_OS_HPP__
  20. #define __PJPP_OS_HPP__
  21. #include <pj/os.h>
  22. #include <pj/string.h>
  23. #include <pj++/types.hpp>
  24. #include <pj++/pool.hpp>
  25. class Pj_Thread;
  26. //
  27. // Thread API.
  28. //
  29. class Pj_Thread_API
  30. {
  31. public:
  32. //
  33. // Create a thread.
  34. //
  35. static pj_status_t create( Pj_Pool *pool, pj_thread_t **thread,
  36. pj_thread_proc *proc, void *arg,
  37. unsigned flags = 0,
  38. const char *name = NULL,
  39. pj_size_t stack_size = 0 )
  40. {
  41. return pj_thread_create(pool->pool_(), name, proc, arg, stack_size,
  42. flags, thread);
  43. }
  44. //
  45. // Register a thread.
  46. //
  47. static pj_status_t register_this_thread( pj_thread_desc desc,
  48. pj_thread_t **thread,
  49. const char *name = NULL )
  50. {
  51. return pj_thread_register( name, desc, thread );
  52. }
  53. //
  54. // Get current thread.
  55. // Will return pj_thread_t (sorry folks, not Pj_Thread).
  56. //
  57. static pj_thread_t *this_thread()
  58. {
  59. return pj_thread_this();
  60. }
  61. //
  62. // Get thread name.
  63. //
  64. static const char *get_name(pj_thread_t *thread)
  65. {
  66. return pj_thread_get_name(thread);
  67. }
  68. //
  69. // Resume thread.
  70. //
  71. static pj_status_t resume(pj_thread_t *thread)
  72. {
  73. return pj_thread_resume(thread);
  74. }
  75. //
  76. // Sleep.
  77. //
  78. static pj_status_t sleep(unsigned msec)
  79. {
  80. return pj_thread_sleep(msec);
  81. }
  82. //
  83. // Join the specified thread.
  84. //
  85. static pj_status_t join(pj_thread_t *thread)
  86. {
  87. return pj_thread_join(thread);
  88. }
  89. //
  90. // Destroy thread
  91. //
  92. static pj_status_t destroy(pj_thread_t *thread)
  93. {
  94. return pj_thread_destroy(thread);
  95. }
  96. };
  97. //
  98. // Thread object.
  99. //
  100. // How to use:
  101. // Derive a class from this class, then override main().
  102. //
  103. class Pj_Thread : public Pj_Object
  104. {
  105. public:
  106. enum Flags
  107. {
  108. FLAG_SUSPENDED = PJ_THREAD_SUSPENDED
  109. };
  110. //
  111. // Default constructor.
  112. //
  113. Pj_Thread()
  114. : thread_(NULL)
  115. {
  116. }
  117. //
  118. // Destroy thread.
  119. //
  120. ~Pj_Thread()
  121. {
  122. destroy();
  123. }
  124. //
  125. // This is the main thread function.
  126. //
  127. virtual int main() = 0;
  128. //
  129. // Start a thread.
  130. //
  131. pj_status_t create( Pj_Pool *pool,
  132. unsigned flags = 0,
  133. const char *thread_name = NULL,
  134. pj_size_t stack_size = PJ_THREAD_DEFAULT_STACK_SIZE)
  135. {
  136. destroy();
  137. return Pj_Thread_API::create( pool, &thread_, &thread_proc, this,
  138. flags, thread_name, stack_size);
  139. }
  140. //
  141. // Get pjlib compatible thread object.
  142. //
  143. pj_thread_t *pj_thread_t_()
  144. {
  145. return thread_;
  146. }
  147. //
  148. // Get thread name.
  149. //
  150. const char *get_name()
  151. {
  152. return Pj_Thread_API::get_name(thread_);
  153. }
  154. //
  155. // Resume a suspended thread.
  156. //
  157. pj_status_t resume()
  158. {
  159. return Pj_Thread_API::resume(thread_);
  160. }
  161. //
  162. // Join this thread.
  163. //
  164. pj_status_t join()
  165. {
  166. return Pj_Thread_API::join(thread_);
  167. }
  168. //
  169. // Destroy thread.
  170. //
  171. pj_status_t destroy()
  172. {
  173. if (thread_) {
  174. Pj_Thread_API::destroy(thread_);
  175. thread_ = NULL;
  176. }
  177. }
  178. protected:
  179. pj_thread_t *thread_;
  180. static int PJ_THREAD_FUNC thread_proc(void *obj)
  181. {
  182. Pj_Thread *thread_class = (Pj_Thread*)obj;
  183. return thread_class->main();
  184. }
  185. };
  186. //
  187. // External Thread
  188. // (threads that were started by external means, i.e. not
  189. // with Pj_Thread::create).
  190. //
  191. // This class will normally be defined as local variable in
  192. // external thread's stack, normally inside thread's main proc.
  193. // But be aware that the handle will be destroyed on destructor!
  194. //
  195. class Pj_External_Thread : public Pj_Thread
  196. {
  197. public:
  198. Pj_External_Thread()
  199. {
  200. }
  201. //
  202. // Register external thread so that pjlib functions can work
  203. // in that thread.
  204. //
  205. pj_status_t register_this_thread( const char *name=NULL )
  206. {
  207. return Pj_Thread_API::register_this_thread(desc_, &thread_,name);
  208. }
  209. private:
  210. pj_thread_desc desc_;
  211. };
  212. //
  213. // Thread specific data/thread local storage/TLS.
  214. //
  215. class Pj_Thread_Local_API
  216. {
  217. public:
  218. //
  219. // Allocate thread local storage (TLS) index.
  220. //
  221. static pj_status_t alloc(long *index)
  222. {
  223. return pj_thread_local_alloc(index);
  224. }
  225. //
  226. // Free TLS index.
  227. //
  228. static void free(long index)
  229. {
  230. pj_thread_local_free(index);
  231. }
  232. //
  233. // Set thread specific data.
  234. //
  235. static pj_status_t set(long index, void *value)
  236. {
  237. return pj_thread_local_set(index, value);
  238. }
  239. //
  240. // Get thread specific data.
  241. //
  242. static void *get(long index)
  243. {
  244. return pj_thread_local_get(index);
  245. }
  246. };
  247. //
  248. // Atomic variable
  249. //
  250. // How to use:
  251. // Pj_Atomic_Var var(pool, 0);
  252. // var.set(..);
  253. //
  254. class Pj_Atomic_Var : public Pj_Object
  255. {
  256. public:
  257. //
  258. // Default constructor, initialize variable with NULL.
  259. //
  260. Pj_Atomic_Var()
  261. : var_(NULL)
  262. {
  263. }
  264. //
  265. // Construct atomic variable.
  266. //
  267. Pj_Atomic_Var(Pj_Pool *pool, pj_atomic_value_t value)
  268. : var_(NULL)
  269. {
  270. create(pool, value);
  271. }
  272. //
  273. // Destructor.
  274. //
  275. ~Pj_Atomic_Var()
  276. {
  277. destroy();
  278. }
  279. //
  280. // Create atomic variable.
  281. //
  282. pj_status_t create( Pj_Pool *pool, pj_atomic_value_t value)
  283. {
  284. destroy();
  285. return pj_atomic_create(pool->pool_(), value, &var_);
  286. }
  287. //
  288. // Destroy.
  289. //
  290. void destroy()
  291. {
  292. if (var_) {
  293. pj_atomic_destroy(var_);
  294. var_ = NULL;
  295. }
  296. }
  297. //
  298. // Get pjlib compatible atomic variable.
  299. //
  300. pj_atomic_t *pj_atomic_t_()
  301. {
  302. return var_;
  303. }
  304. //
  305. // Set the value.
  306. //
  307. void set(pj_atomic_value_t val)
  308. {
  309. pj_atomic_set(var_, val);
  310. }
  311. //
  312. // Get the value.
  313. //
  314. pj_atomic_value_t get()
  315. {
  316. return pj_atomic_get(var_);
  317. }
  318. //
  319. // Increment.
  320. //
  321. void inc()
  322. {
  323. pj_atomic_inc(var_);
  324. }
  325. //
  326. // Increment and get the result.
  327. //
  328. pj_atomic_value_t inc_and_get()
  329. {
  330. return pj_atomic_inc_and_get(var_);
  331. }
  332. //
  333. // Decrement.
  334. //
  335. void dec()
  336. {
  337. pj_atomic_dec(var_);
  338. }
  339. //
  340. // Decrement and get the result.
  341. //
  342. pj_atomic_value_t dec_and_get()
  343. {
  344. return pj_atomic_dec_and_get(var_);
  345. }
  346. //
  347. // Add the variable.
  348. //
  349. void add(pj_atomic_value_t value)
  350. {
  351. pj_atomic_add(var_, value);
  352. }
  353. //
  354. // Add the variable and get the value.
  355. //
  356. pj_atomic_value_t add_and_get(pj_atomic_value_t value)
  357. {
  358. return pj_atomic_add_and_get(var_, value );
  359. }
  360. private:
  361. pj_atomic_t *var_;
  362. };
  363. //
  364. // Mutex
  365. //
  366. class Pj_Mutex : public Pj_Object
  367. {
  368. public:
  369. //
  370. // Mutex type.
  371. //
  372. enum Type
  373. {
  374. DEFAULT = PJ_MUTEX_DEFAULT,
  375. SIMPLE = PJ_MUTEX_SIMPLE,
  376. RECURSE = PJ_MUTEX_RECURSE,
  377. };
  378. //
  379. // Default constructor will create default mutex.
  380. //
  381. explicit Pj_Mutex(Pj_Pool *pool, Type type = DEFAULT,
  382. const char *name = NULL)
  383. : mutex_(NULL)
  384. {
  385. create(pool, type, name);
  386. }
  387. //
  388. // Destructor.
  389. //
  390. ~Pj_Mutex()
  391. {
  392. destroy();
  393. }
  394. //
  395. // Create mutex.
  396. //
  397. pj_status_t create( Pj_Pool *pool, Type type, const char *name = NULL)
  398. {
  399. destroy();
  400. return pj_mutex_create( pool->pool_(), name, type,
  401. &mutex_ );
  402. }
  403. //
  404. // Create simple mutex.
  405. //
  406. pj_status_t create_simple( Pj_Pool *pool,const char *name = NULL)
  407. {
  408. return create(pool, SIMPLE, name);
  409. }
  410. //
  411. // Create recursive mutex.
  412. //
  413. pj_status_t create_recursive( Pj_Pool *pool, const char *name = NULL )
  414. {
  415. return create(pool, RECURSE, name);
  416. }
  417. //
  418. // Get pjlib compatible mutex object.
  419. //
  420. pj_mutex_t *pj_mutex_t_()
  421. {
  422. return mutex_;
  423. }
  424. //
  425. // Destroy mutex.
  426. //
  427. void destroy()
  428. {
  429. if (mutex_) {
  430. pj_mutex_destroy(mutex_);
  431. mutex_ = NULL;
  432. }
  433. }
  434. //
  435. // Lock mutex.
  436. //
  437. pj_status_t acquire()
  438. {
  439. return pj_mutex_lock(mutex_);
  440. }
  441. //
  442. // Unlock mutex.
  443. //
  444. pj_status_t release()
  445. {
  446. return pj_mutex_unlock(mutex_);
  447. }
  448. //
  449. // Try locking the mutex.
  450. //
  451. pj_status_t tryacquire()
  452. {
  453. return pj_mutex_trylock(mutex_);
  454. }
  455. private:
  456. pj_mutex_t *mutex_;
  457. };
  458. //
  459. // Semaphore
  460. //
  461. class Pj_Semaphore : public Pj_Object
  462. {
  463. public:
  464. //
  465. // Construct semaphore
  466. //
  467. Pj_Semaphore(Pj_Pool *pool, unsigned max,
  468. unsigned initial = 0, const char *name = NULL)
  469. : sem_(NULL)
  470. {
  471. create(pool, max, initial, name);
  472. }
  473. //
  474. // Destructor.
  475. //
  476. ~Pj_Semaphore()
  477. {
  478. destroy();
  479. }
  480. //
  481. // Create semaphore
  482. //
  483. pj_status_t create( Pj_Pool *pool, unsigned max,
  484. unsigned initial = 0, const char *name = NULL )
  485. {
  486. destroy();
  487. return pj_sem_create( pool->pool_(), name, initial, max, &sem_);
  488. }
  489. //
  490. // Destroy semaphore.
  491. //
  492. void destroy()
  493. {
  494. if (sem_) {
  495. pj_sem_destroy(sem_);
  496. sem_ = NULL;
  497. }
  498. }
  499. //
  500. // Get pjlib compatible semaphore object.
  501. //
  502. pj_sem_t *pj_sem_t_()
  503. {
  504. return (pj_sem_t*)this;
  505. }
  506. //
  507. // Wait semaphore.
  508. //
  509. pj_status_t wait()
  510. {
  511. return pj_sem_wait(this->pj_sem_t_());
  512. }
  513. //
  514. // Wait semaphore.
  515. //
  516. pj_status_t acquire()
  517. {
  518. return wait();
  519. }
  520. //
  521. // Try wait semaphore.
  522. //
  523. pj_status_t trywait()
  524. {
  525. return pj_sem_trywait(this->pj_sem_t_());
  526. }
  527. //
  528. // Try wait semaphore.
  529. //
  530. pj_status_t tryacquire()
  531. {
  532. return trywait();
  533. }
  534. //
  535. // Post semaphore.
  536. //
  537. pj_status_t post()
  538. {
  539. return pj_sem_post(this->pj_sem_t_());
  540. }
  541. //
  542. // Post semaphore.
  543. //
  544. pj_status_t release()
  545. {
  546. return post();
  547. }
  548. private:
  549. pj_sem_t *sem_;
  550. };
  551. //
  552. // Event object.
  553. //
  554. class Pj_Event
  555. {
  556. public:
  557. //
  558. // Construct event object.
  559. //
  560. Pj_Event( Pj_Pool *pool, bool manual_reset = false,
  561. bool initial = false, const char *name = NULL )
  562. : event_(NULL)
  563. {
  564. create(pool, manual_reset, initial, name);
  565. }
  566. //
  567. // Destructor.
  568. //
  569. ~Pj_Event()
  570. {
  571. destroy();
  572. }
  573. //
  574. // Create event object.
  575. //
  576. pj_status_t create( Pj_Pool *pool, bool manual_reset = false,
  577. bool initial = false, const char *name = NULL)
  578. {
  579. destroy();
  580. return pj_event_create(pool->pool_(), name, manual_reset, initial,
  581. &event_);
  582. }
  583. //
  584. // Get pjlib compatible event object.
  585. //
  586. pj_event_t *pj_event_t_()
  587. {
  588. return event_;
  589. }
  590. //
  591. // Destroy event object.
  592. //
  593. void destroy()
  594. {
  595. if (event_) {
  596. pj_event_destroy(event_);
  597. event_ = NULL;
  598. }
  599. }
  600. //
  601. // Wait.
  602. //
  603. pj_status_t wait()
  604. {
  605. return pj_event_wait(event_);
  606. }
  607. //
  608. // Try wait.
  609. //
  610. pj_status_t trywait()
  611. {
  612. return pj_event_trywait(event_);
  613. }
  614. //
  615. // Set event state to signalled.
  616. //
  617. pj_status_t set()
  618. {
  619. return pj_event_set(this->pj_event_t_());
  620. }
  621. //
  622. // Release one waiting thread.
  623. //
  624. pj_status_t pulse()
  625. {
  626. return pj_event_pulse(this->pj_event_t_());
  627. }
  628. //
  629. // Set a non-signalled.
  630. //
  631. pj_status_t reset()
  632. {
  633. return pj_event_reset(this->pj_event_t_());
  634. }
  635. private:
  636. pj_event_t *event_;
  637. };
  638. //
  639. // Timestamp
  640. //
  641. class Pj_Timestamp
  642. {
  643. public:
  644. pj_status_t get_timestamp()
  645. {
  646. return pj_get_timestamp(&ts_);
  647. }
  648. Pj_Timestamp& operator += (const Pj_Timestamp &rhs)
  649. {
  650. pj_add_timestamp(&ts_, &rhs.ts_);
  651. return *this;
  652. }
  653. Pj_Timestamp& operator -= (const Pj_Timestamp &rhs)
  654. {
  655. pj_sub_timestamp(&ts_, &rhs.ts_);
  656. return *this;
  657. }
  658. Pj_Time_Val to_time() const
  659. {
  660. Pj_Timestamp zero;
  661. pj_memset(&zero, 0, sizeof(zero));
  662. return Pj_Time_Val(pj_elapsed_time(&zero.ts_, &ts_));
  663. }
  664. pj_uint32_t to_msec() const
  665. {
  666. Pj_Timestamp zero;
  667. pj_memset(&zero, 0, sizeof(zero));
  668. return pj_elapsed_msec(&zero.ts_, &ts_);
  669. }
  670. pj_uint32_t to_usec() const
  671. {
  672. Pj_Timestamp zero;
  673. pj_memset(&zero, 0, sizeof(zero));
  674. return pj_elapsed_usec(&zero.ts_, &ts_);
  675. }
  676. pj_uint32_t to_nanosec() const
  677. {
  678. Pj_Timestamp zero;
  679. pj_memset(&zero, 0, sizeof(zero));
  680. return pj_elapsed_nanosec(&zero.ts_, &ts_);
  681. }
  682. pj_uint32_t to_cycle() const
  683. {
  684. Pj_Timestamp zero;
  685. pj_memset(&zero, 0, sizeof(zero));
  686. return pj_elapsed_cycle(&zero.ts_, &ts_);
  687. }
  688. private:
  689. pj_timestamp ts_;
  690. };
  691. //
  692. // OS abstraction.
  693. //
  694. class Pj_OS_API
  695. {
  696. public:
  697. //
  698. // Get current time.
  699. //
  700. static pj_status_t gettimeofday( Pj_Time_Val *tv )
  701. {
  702. return pj_gettimeofday(tv);
  703. }
  704. //
  705. // Parse to time of day.
  706. //
  707. static pj_status_t time_decode( const Pj_Time_Val *tv,
  708. pj_parsed_time *pt )
  709. {
  710. return pj_time_decode(tv, pt);
  711. }
  712. //
  713. // Parse from time of day.
  714. //
  715. static pj_status_t time_encode( const pj_parsed_time *pt,
  716. Pj_Time_Val *tv)
  717. {
  718. return pj_time_encode(pt, tv);
  719. }
  720. //
  721. // Convert to GMT.
  722. //
  723. static pj_status_t time_local_to_gmt( Pj_Time_Val *tv )
  724. {
  725. return pj_time_local_to_gmt( tv );
  726. }
  727. //
  728. // Convert time to local.
  729. //
  730. static pj_status_t time_gmt_to_local( Pj_Time_Val *tv)
  731. {
  732. return pj_time_gmt_to_local( tv );
  733. }
  734. };
  735. //
  736. // Timeval inlines.
  737. //
  738. inline pj_status_t Pj_Time_Val::gettimeofday()
  739. {
  740. return Pj_OS_API::gettimeofday(this);
  741. }
  742. inline pj_parsed_time Pj_Time_Val::decode()
  743. {
  744. pj_parsed_time pt;
  745. Pj_OS_API::time_decode(this, &pt);
  746. return pt;
  747. }
  748. inline pj_status_t Pj_Time_Val::encode(const pj_parsed_time *pt)
  749. {
  750. return Pj_OS_API::time_encode(pt, this);
  751. }
  752. inline pj_status_t Pj_Time_Val::to_gmt()
  753. {
  754. return Pj_OS_API::time_local_to_gmt(this);
  755. }
  756. inline pj_status_t Pj_Time_Val::to_local()
  757. {
  758. return Pj_OS_API::time_gmt_to_local(this);
  759. }
  760. #endif /* __PJPP_OS_HPP__ */