1.使用前的初始化和使用后的清理
PJSIP库里面封装了很多线程内存池;而且很多对象都是基于内存池创建的,所以几乎所以的库都需要初始化或创建
下面是pjlib,pjlib-util,pjnath,pjsua-lib库的初始化和关闭
显示行号 复制代码 这是一段程序代码。
- pj_status_t status;
- status = pj_init(); //初始化pjlib库返回PJ_SUCCESS表示成功
- status = pjlib_util_init(); //初始化pjlib-util库
- status = pjnath_init(); //初始化pjnath库
- status = pjsua_create(); //初始化pjsua-lib库;(里面初始化了pjlib,pjlib-util,pjnath)
-
- pj_shutdown(); //pjlib停止
- pjsua_destroy(); //pjsua-lib库的清理
.src_container{background-color:#e7e5dc; width:99%; overflow:hidden; margin:12px 0 12px 0 !important; padding:0px 3px 3px 0px} .src_container .titlebar{ background-color:#d4dfff; border:1px solid #4f81bd; border-bottom:0; padding:3px 24px; margin:0; width:auto; line-height:120%; overflow:hidden; text-align:left; font-size:12px} .src_container .toolbar{ display:inline; font-weight:normal; font-size:100%; float:right; cursor:hand; color:#00f; text-align:left; overflow:hidden} .toolbar span.button{ display:inline; font-weight:normal; font-size:100%; cursor:hand; color:#00f; text-align:left; overflow:hidden; cursor:pointer;} .src_container div.clientarea{ background-color:white; border:1px solid #4f81bd; margin:0; width:auto !important; width:100%; height:auto; overflow:auto; text-align:left; font-size:12px; font-family: "courier new","consolas","fixedsys",courier,monospace,serif} .src_container ol.mainarea{ padding:0 0 0 52px; margin:0; background-color:#f7f7ff !important} .number_show{ padding-left:52px !important; list-style:decimal outside !important} .number_show li{ list-style:decimal outside !important; border-left:1px dotted #4f81bd} .number_hide{ padding-left:0px !important; list-style-type:none !important} .number_hide li{ list-style-type:none !important; border-left:0px} ol.mainarea li{ display:list-item !important; font-size:12px !important; margin:0 !important; line-height:18px !important; padding:0 0 0 0px !important; background-color:#f7f7ff !important; color:#4f81bd} ol.mainarea li pre{color:black; line-height:18px; padding:0 0 0 12px !important; margin:0em; background-color:#fff !important} .linewrap ol.mainarea li pre{white-space:pre-wrap; white-space:-moz-pre-wrapwhite-space:-pre-wrap; white-space:-o-pre-wrap; word-wrap:break-word} ol.mainarea li pre.alt{ background-color:#f7f7ff !important}
2.缓冲池和内存池(caching,pool)
pjsip的内存池的使用规则:
每个内存池都是基于内存池工厂创建的;pjsip有一个默认的内存池工厂pj_caching_pool;
我喜欢把它叫做缓冲池;将来清理内存池的时候,可以关闭内存池也可直接关闭缓冲池;
pj_caching_pool cp;
pj_caching_pool_init(&cp, NULL, 1024*1024 ); //缓冲池
pj_caching_pool_destroy(&cp); //释放工厂
pj_pool_t pool = pj_pool_create(&cp.factory, "name", 1024, 1024, NULL); //创建内存池
pj_pool_release(&pool); //释放内存池到工厂中,直接释放工厂可省略这一步
void* p = pj_pool_alloc(pool, size); //在内存中开辟一个空间
注:适当的初始化大小;内存池只能增加不能减小
由于pjlib很多内部对象都用内存池,所以在对象释放之前不能释放内存池。
使用缓冲池和内存池
- //系统初始化的时候调用
- void create()
- {
- //初始化pjlib库返回PJ_SUCCESS表示成功
- pj_status_t status = pj_init();
-
- pj_caching_pool_init(&this->m_caching, NULL, 0);
- this->m_pool = pj_pool_create(&this->m_caching.factory, "", 256, 256, NULL);
-
- //初始化mutex
- pj_mutex_create(this->m_pool, "", PJ_MUTEX_SIMPLE, &this->m_pool_mutex);
-
- //创建一个lock给定时器用
- pj_lock_create_simple_mutex(this->m_pool, "timer_lock", &this->timer_heap_lock);
-
- //在内存池上开辟一块空间
- char *pmem = (char*)pj_pool_alloc(this->m_pool, 1024);
-
- //创建一个定时器堆
- pj_timer_heap_create(this->m_pool, MAX_TIMER_COUTN, &this->timer_heap);
-
- //给定时器加锁; 将来自动删除该锁,无需手工删除
- pj_timer_heap_set_lock(this->timer_heap, this->timer_heap_lock, true);
- }
-
- //系统退出的时候调用
- void destroy()
- {
- //删除mutex
- pj_mutex_destroy(this->m_pool_mutex);
-
- //删除定时器的堆
- pj_timer_heap_destroy(this->timer_heap);
-
- //清理内存池,这一步也可以删略;让caching_pool来清理
- pj_pool_destroy_int(this->m_pool);
-
- //清理缓冲池;所有在缓冲池建立的内存池都会被清理掉
- pj_caching_pool_destroy(&this->m_caching);
-
- //pjlib停止
- pj_shutdown();
- }
.src_container{background-color:#e7e5dc; width:99%; overflow:hidden; margin:12px 0 12px 0 !important; padding:0px 3px 3px 0px} .src_container .titlebar{ background-color:#d4dfff; border:1px solid #4f81bd; border-bottom:0; padding:3px 24px; margin:0; width:auto; line-height:120%; overflow:hidden; text-align:left; font-size:12px} .src_container .toolbar{ display:inline; font-weight:normal; font-size:100%; float:right; cursor:hand; color:#00f; text-align:left; overflow:hidden} .toolbar span.button{ display:inline; font-weight:normal; font-size:100%; cursor:hand; color:#00f; text-align:left; overflow:hidden; cursor:pointer;} .src_container div.clientarea{ background-color:white; border:1px solid #4f81bd; margin:0; width:auto !important; width:100%; height:auto; overflow:auto; text-align:left; font-size:12px; font-family: "courier new","consolas","fixedsys",courier,monospace,serif} .src_container ol.mainarea{ padding:0 0 0 52px; margin:0; background-color:#f7f7ff !important} .number_show{ padding-left:52px !important; list-style:decimal outside !important} .number_show li{ list-style:decimal outside !important; border-left:1px dotted #4f81bd} .number_hide{ padding-left:0px !important; list-style-type:none !important} .number_hide li{ list-style-type:none !important; border-left:0px} ol.mainarea li{ display:list-item !important; font-size:12px !important; margin:0 !important; line-height:18px !important; padding:0 0 0 0px !important; background-color:#f7f7ff !important; color:#4f81bd} ol.mainarea li pre{color:black; line-height:18px; padding:0 0 0 12px !important; margin:0em; background-color:#fff !important} .linewrap ol.mainarea li pre{white-space:pre-wrap; white-space:-moz-pre-wrapwhite-space:-pre-wrap; white-space:-o-pre-wrap; word-wrap:break-word} ol.mainarea li pre.alt{ background-color:#f7f7ff !important}
3.线程的介绍,及其线程的封装和使用
1.外部函数或线程使用到pjsip的时候,必须注册线程
隐藏行号 复制代码 注册线程
- pj_thread_desc desc;
- pj_bzero(desc, sizeof(desc));
- pj_thread_t *thread_;
- if (pj_thread_register("", desc, &thread_) != PJ_SUCCESS)
- return 0; /* 失败*/
-
.src_container{background-color:#e7e5dc; width:99%; overflow:hidden; margin:12px 0 12px 0 !important; padding:0px 3px 3px 0px} .src_container .titlebar{ background-color:#d4dfff; border:1px solid #4f81bd; border-bottom:0; padding:3px 24px; margin:0; width:auto; line-height:120%; overflow:hidden; text-align:left; font-size:12px} .src_container .toolbar{ display:inline; font-weight:normal; font-size:100%; float:right; cursor:hand; color:#00f; text-align:left; overflow:hidden} .toolbar span.button{ display:inline; font-weight:normal; font-size:100%; cursor:hand; color:#00f; text-align:left; overflow:hidden; cursor:pointer;} .src_container div.clientarea{ background-color:white; border:1px solid #4f81bd; margin:0; width:auto !important; width:100%; height:auto; overflow:auto; text-align:left; font-size:12px; font-family: "courier new","consolas","fixedsys",courier,monospace,serif} .src_container ol.mainarea{ padding:0 0 0 52px; margin:0; background-color:#f7f7ff !important} .number_show{ padding-left:52px !important; list-style:decimal outside !important} .number_show li{ list-style:decimal outside !important; border-left:1px dotted #4f81bd} .number_hide{ padding-left:0px !important; list-style-type:none !important} .number_hide li{ list-style-type:none !important; border-left:0px} ol.mainarea li{ display:list-item !important; font-size:12px !important; margin:0 !important; line-height:18px !important; padding:0 0 0 0px !important; background-color:#f7f7ff !important; color:#4f81bd} ol.mainarea li pre{color:black; line-height:18px; padding:0 0 0 12px !important; margin:0em; background-color:#fff !important} .linewrap ol.mainarea li pre{white-space:pre-wrap; white-space:-moz-pre-wrapwhite-space:-pre-wrap; white-space:-o-pre-wrap; word-wrap:break-word} ol.mainarea li pre.alt{ background-color:#f7f7ff !important}
function CopyCode(key){var codeElement=null;var trElements=document.all.tags("ol");var i;for(i=0;i
2.线程的创建和使用
pj_thread_create(pool*,"", function, *arg, stack_size, flag, **pj_thread_t)//创建一个线程
pj_thread_destroy(thread); //注销一个线程
pj_thread_resume(thread); //线程继续
pj_thread_sleep(1500); //当前的线程暂停1500毫秒
pj_thread_join(thrad); //等待线程结束
pj_thread_proc函数原型是:int thread_func(void * argv);
3.对pjlib的thread的线程的封装
1: class CSipThread 2: { 3: //1.实现一个int ()(void*)的函数,且在结束的地方设置m_thread_t=NULL 4: pj_thread_t *m_thread_t; 5: protected: 6: 7: /* int (pj_thread_proc)(void*); 8: * 线程函数;子类需要使用static函数来实现 9: * 子类函数中在结束的时候:必须将m_thread_t = NULL; 10: */ 11: pj_thread_proc *m_thread_function; 12: 13: /* 这个是实现函数; 14: * 子类需要实现一个run()的函数;在run函数中调用run_父类的函数 15: */ 16: virtual void run_(pj_pool_t *pool, pj_thread_proc *function); 17: public: 18: CSipThread(); 19: virtual ~CSipThread(); 20: virtual bool thread_running(); 21: 22: //等待线程结束,自动释放资源,且会将m_thread_t=NULL 23: virtual void thread_join(); 24: 25: //在线程自己退出的时候,没有需要手工释放资源,和设置m_thread_t=NULL 26: virtual void thread_destroy(); 27: }; 28: CSipThread::CSipThread() 29: { 30: this->m_thread_t = NULL; 31: } 32: CSipThread::~CSipThread() 33: { 34: 35: } 36: void CSipThread::run_(pj_pool_t *pool, pj_thread_proc *function) 37: { 38: if ( this->thread_running()) 39: return; 40: pj_status_t status = pj_thread_create(pool, "", function, this, 41: PJ_THREAD_DEFAULT_STACK_SIZE, NULL, &this->m_thread_t); 42: if (status != PJ_SUCCESS) 43: { 44: CFunctions::write_log(LM_ERROR, "Can't create timer thread. [result=%d]..\n", status); 45: } 46: } 47: bool CSipThread::thread_running() 48: { 49: if (this->m_thread_t == NULL) 50: return false; 51: else 52: return true; 53: } 54: 55: void CSipThread::thread_join() 56: { 57: if (this->m_thread_t == NULL) 58: return; 59: 60: // 等待线程结束 61: pj_thread_join(this->m_thread_t); 62: } 63: 64: void CSipThread::thread_destroy() 65: { 66: pj_thread_destroy(this->m_thread_t); 67: this->m_thread_t = NULL; 68: }
4.使用封装起来的thread线程对象
1: /* 使用封装后的线程注意事项 2: * 1. 必须定义一个static的静态函数 3: * 2. 在静态函数结束的时候必须调用thread_destroy(); 4: */ 5: class CSendThread : public CSipThread 6: { 7: //线程函数;在函数退出的时候必须调用thread_destroy(); 8: static int thread_func(void * argv); 9: public: 10: CSendThread(void); 11: virtual ~CSendThread(void); 12: 13: //再次封装了run_函数 14: void run(); 15: } 16: 17: void CSendThread::run() 18: { 19: if ( this->thread_running()) 20: return; 21: 22: SIP_GUARD(CInterFace::instance()->m_pool_mutex, obj); 23: 24: //调用父类的run_函数进行创建函数,开始运行;注意如果线程已经存在,那么直接返回 25: //不会再创建一个线程 26: this->run_(CInterFace::instance()->m_pool, &CSendThread::thread_func); 27: } 28: 29: int CSendThread::thread_func(void * argv) 30: { 31: // 线程函数的参数默认是当前对象,等同于this指针 32: CSendThread *this_thread = (CSendThread*)argv; 33: 34: thread_end: 35: // 在线程结束的时候,一定要调用thread_destroy();来删除线程 36: this_thread->thread_destroy(); 37: return 0; 38: }
4.互斥和锁,及其封装(mutex)
pj_mutex_create(this->m_pool, "", PJ_MUTEX_SIMPLE, &this->m_pool_mutex); //创建一个锁指针
pj_mutex_destroy(this->m_pool_mutex); //删除锁指针
pj_mutex_lock(m_mutex); //加锁
pj_mutex_unlock(m_mutex); //解锁
1: /* 封装了mutex的使用方法 2: * 在创建对象时加锁、删除对象时解锁 3: */ 4: class Sip_Lock 5: { 6: pj_mutex_t *m_mutex; 7: public: 8: Sip_Lock(pj_mutex_t *mutex) 9: { 10: this->m_mutex = mutex; 11: pj_mutex_lock(m_mutex); 12: } 13: virtual ~Sip_Lock() 14: { 15: pj_mutex_unlock(m_mutex); 16: this->m_mutex = NULL; 17: } 18: }; 19: 20: /* 封装了sip_lock的使用,直接使用宏定义进行互斥 */ 21: #define SIP_GUARD(MUTEX, OBJ) Sip_Lock OBJ(MUTEX);
5.定时器(heap,callback,thread)
//创建定时器堆,设置定时器堆pool大小
pj_timer_heap_create(this->m_pool, MAX_TIMER_COUTN, &this->timer_heap);
pj_timer_heap_set_max_timed_out_per_poll(this->timer_heap, 20);
//对定时器加锁是lcok类型
pj_timer_heap_set_lock(this->timer_heap, this->timer_heap_lock, true);
//启动定时器轮询的线程
this->run_(this->m_pool, &CInterFace::timer_thread_fun);
//设置一个定时器
pj_timer_heap_schedule(this->timer_heap, entry, delay);
//取消一个定时器
pj_timer_heap_cancel(this->timer_heap, entry);
//定时器的入口点定义
struct pj_timer_entry
{
void *user_data; // 定时器的用户数据;C++通常用类对象;C通常用struct
int id; // 绝对的ID号;用来区分当user_data和cb都相同的情况
pj_timer_heap_callback *cb; // 定时器中的回调函数
};
//定时器回调函数的原型
void timer_callback(pj_timer_heap_t *timer_heap,struct pj_timer_entry *entry);
一个定时器的使用例子:
1. 创建一个定时器、创建一个线程
2. 创建一个定时器入口entry
3. 创建一个定时器的回调函数,在回调函数中必须重新将entry加入堆中
1: //创建定时器堆,设置定时器堆pool大小; 加锁; 2: pj_timer_heap_create(this->m_pool, MAX_TIMER_COUTN, &this->timer_heap); 3: pj_timer_heap_set_max_timed_out_per_poll(this->timer_heap, 20); 4: pj_timer_heap_set_lock(this->timer_heap, this->timer_heap_lock, true); 5: 6: //启动定时器轮询的线程 7: this->run_(this->m_pool, &CInterFace::timer_thread_fun); 8: 9: 10: //定时器的线程函数 11: int CInterFace::timer_thread_fun(void* argv) 12: { 13: CInterFace *this_thread = (CInterFace*)argv; 14: int rc; 15: while ( !CInterFace::instance()->application_exit() ) 16: { 17: pj_thread_sleep(1); 18: 19: #if defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0 20: /* On Symbian, we must use OS poll (Active Scheduler poll) since 21: * timer is implemented using Active Object. 22: */ 23: rc = 0; 24: while (pj_symbianos_poll(-1, 0)) 25: ++rc; 26: #else 27: PJ_USE_EXCEPTION; 28: PJ_TRY 29: { 30: rc = pj_timer_heap_poll(CInterFace::instance()->timer_heap, NULL); 31: } 32: PJ_CATCH_ANY 33: { 34: 35: } 36: PJ_END; 37: #endif 38: } 39: 40: // 定时器轮询的线程退出;必须手工删除pj_thread_t指针,因为它使用了内存池! 41: CFunctions::write_log(LM_DEBUG, "pj_timer_heap_pool, ending.\n"); 42: this_thread->thread_destroy(); 43: return 0; 44: } 45: 46: 47: //启动一个定时器:也就是将一个entry添加到堆上面 48: void CInterFace::start_timer(pj_timer_entry* entry, pj_time_val *delay) 49: { 50: if ( !this->thread_running()) 51: return; 52: 53: SIP_GUARD(this->timer_heap_mutex, obj); 54: pj_timer_heap_schedule(this->timer_heap, entry, delay); 55: } 56: 57: //取消一个定时器:从堆上删除一个entry 58: void CInterFace::stop_timer(pj_timer_entry* entry) 59: { 60: if ( !this->thread_running()) 61: return; 62: 63: SIP_GUARD(this->timer_heap_mutex, obj); 64: pj_timer_heap_cancel(this->timer_heap, entry); 65: } 66: 67: //启动上报速度和进度的定时器 68: bool CBaseFile::start_timer_speedProgress() 69: { 70: this->m_timer_speed_tval.msec = 0; 71: this->m_timer_speed_tval.sec = 1; 72: this->m_timer_speed.user_data = this; 73: this->m_timer_speed.cb = &CBaseFile::callback_speed; 74: SIP_GUARD(this->m_run_speed_mutex, obj); 75: this->m_run_speed = true; 76: CInterFace::instance()->start_timer(&this->m_timer_speed, &this->m_timer_speed_tval); 77: return true; 78: } 79: 80: //取消上报进度和速度的定时器 81: void CBaseFile::stop_timer_speedProgress() 82: { 83: SIP_GUARD(this->m_run_speed_mutex, obj); 84: this->m_run_speed = false; 85: CInterFace::instance()->stop_timer(&this->m_timer_speed); 86: } 87: 88: //上报进度和速度的回调函数 89: void CBaseFile::callback_speed(pj_timer_heap_t *timer_heap, pj_timer_entry *entry) 90: { 91: // 上报速度和状态的的 92: if (entry->user_data != NULL) 93: { 94: CBaseFile *file = (CBaseFile*)entry->user_data; 95: 96: uint speed_ = 0; 97: uint progress_ = 0; 98: file->get_speed_progress(speed_, progress_); 99: 100: if ( file->m_ice_session->is_running()) 101: { 102: CInterFace::instance()->report_speed( 103: file->get_userid().c_str(), 104: file->get_fileName().c_str(), 105: file->get_guid(), 106: speed_, 107: progress_); 108: } 109: 110: // 由于定时select出来后,就从堆上删除了;所以需要一直触发的定时器, 111: // 就必须在回调函数中,重新想堆中添加entry! 112: SIP_GUARD(file->m_run_speed_mutex, obj); 113: if ( file->m_run_speed) 114: CInterFace::instance()->start_timer(entry, &file->m_timer_speed_tval); 115: } 116: }
6.pj_str_t字符串
7.socket的封装和使用