os.hpp 15 KB

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