精华内容
下载资源
问答
  • Jthread

    2018-03-23 22:03:30
    此为最新的jthread 库,搭配JRTPLIB来使用,提供了方法传输RTP流,避免了UDP丢包的情况
  • JThread-开源

    2021-06-29 00:57:56
    JThread - 一个面向对象的、Java 之类的 C++ 线程库! 线程和同步类的系统独立 OO 架构 - 将操作系统独立接口和相关实现分开。
  • C++20 jthread

    千次阅读 2020-02-28 16:23:49
    vs2019 C++20 jthread01 jthread的一个实现02 jthread用法02.01 cppreference上面的介绍02.02 可协作中断的用法02.03 NICOLAI JOSUTTIS提供了大量测试用例 jthread是有自动合并和取消支持的 std::thread。jthread...

    jthread是有自动合并和取消支持的 std::threadjthread包装了一下thread,提供了线程运行中停止的接口。jthread定义在<thread>头文件中。
    使用取消功能需要用到std::stop_token。参考:<stop_token>
    建议以后使用thread的都开始使用jthread,不必等到c++20出来。

    1. std::jthread对象销毁时,会调用join,等待其所表示的执行结束。
    2. 支持外部请求中止(通过get_stop_source、get_stop_token和request_stop)。
      std::jthread为了实现上述新功能,带来了额外的性能开销(主要是多了一个成员变量)。而根据C++一直以来“不为不使用的功能付费”的设计哲学,他们自然就把这些新功能拆出来新做了一个类。1

    01 jthread的一个实现

    NICOLAI JOSUTTIS [尼古拉·乔苏蒂斯]2关于jthread的一个实现:
    https://github.com/josuttis/jthread
    这个实现没有使用C++20的新特性。只有jthread.hppstop_token.hpp两个文件,700多行代码。
    https://github.com/josuttis/jthread/blob/master/source/jthread.hpp
    https://github.com/josuttis/jthread/blob/master/source/stop_token.hpp

    02 jthread用法

    文中所有提到的代码,整理在:https://github.com/5455945/cpp_demo/tree/master/C%2B%2B20/jthread

    02.01 cppreference上面的介绍

    jthread在基本用法上面完全兼容thread。
    https://zh.cppreference.com/w/cpp/thread/jthread/jthread

    // https://zh.cppreference.com/w/cpp/thread/jthread/jthread
    #include <iostream>
    #include <utility>
    #include <thread>
    #include <chrono>
    #include "jthread.hpp" // https://github.com/josuttis/jthread/tree/master/source
    
    void f1(int n)
    {
        for (int i = 0; i < 5; ++i) {
            std::cout << "Thread 1 executing\n";
            ++n;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    
    void f2(int& n)
    {
        for (int i = 0; i < 5; ++i) {
            std::cout << "Thread 2 executing\n";
            ++n;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    
    class foo
    {
    public:
        void bar()
        {
            for (int i = 0; i < 5; ++i) {
                std::cout << "Thread 3 executing\n";
                ++n;
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        }
        int n = 0;
    };
    
    class baz
    {
    public:
        void operator()()
        {
            for (int i = 0; i < 5; ++i) {
                std::cout << "Thread 4 executing\n";
                ++n;
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        }
        int n = 0;
    };
    
    void test_jthread_cppreference01()
    {
        int n = 0;
        foo f;
        baz b;
        std::jthread t0; // t0 不是线程
        std::jthread t1(f1, n + 1); // 按值传递
        std::jthread t2a(f2, std::ref(n)); // 按引用传递
        std::jthread t2b(std::move(t2a)); // t2b 现在运行 f2() 。 t2a 不再是线程
        std::jthread t3(&foo::bar, &f); // t3 在对象 f 上运行 foo::bar()
        std::jthread t4(b); // t4 在对象 b 上运行 baz::operator()
        t1.join();
        t2b.join();
        t3.join();
        std::cout << "Final value of n is " << n << '\n';
        std::cout << "Final value of foo::n is " << f.n << '\n';
        // t4 在析构时结合
    }
    

    02.02 可协作中断的用法

    参考 C ++ 20中的新线程(jthread)功能
    使用request_stop()jthread线程发送停止线程请求;在jthread线程中使用stop_requested()来判断是否收到停止线程请求。如果收到停止请求,即做出退出线程反应。

    void sleep(const int seconds) {
    	std::this_thread::sleep_for(std::chrono::seconds(seconds));
    }
    
    void test_jthread03() {
    	std::jthread jt{ [](std::stop_token st) {
    		while (!st.stop_requested()) { // 有停止线程请求的处理
    			std::cout << "Doing work\n";
    			sleep(1);
    		}
    	} };
    	sleep(5);
    	jt.request_stop(); // 请求线程停止,因有响应停止请求而终止线程
    	jt.join();
    }
    

    02.03 NICOLAI JOSUTTIS提供了大量测试用例

    https://github.com/josuttis/jthread/tree/master/source中提供了大量测试用例,对理解jthread的用法很有帮助。


    1. std::jthread与std::thread的区别是什么? ↩︎

    2. 《C++标准库(第2版)》、《C ++ 17 –完整指南》作者 ↩︎

    展开全文
  • jthread-1.3.1.rar

    2018-12-04 08:48:58
    jthread-1.3.1.rar
  • jthread jrtplib

    2010-01-20 19:42:36
    jthread-1.2.1.tar.gz jrtplib-3.7.1.tar.gz
  • JThread manual

    2009-05-18 09:47:05
    JThread 的功能和使用描述,可以对SIP的应用有很大在、帮助。
  • jthread库分析二:JThread

    千次阅读 2014-02-11 14:57:35
    JThread库2

    JThread类的定义如下:

    class JThread
    {
    public:
    	JThread();
    	virtual ~JThread();
    	int Start();
    	int Kill();
    	virtual void *Thread() = 0;
    	bool IsRunning();
    	void *GetReturnValue();
    protected:
    	void ThreadStarted();
    };
    可以通过继承JThread类创建自己的线程。Thread方法将会在新线程中执行,子类应该实现Thread方法。实现的Thread方法中必须立即调用ThreadStarted方法。

    为了启动线程,需要调用Start方法。只有当你的Thread函数调用了ThreadStarted方法后,Start方法才会返回。当Start方法返回后,你的Thread实现一定在运行。当然,你可以调用IsRunning函数检查线程是否还在运行。如果线程已结束,那么你可以调用GetReturnValue获得返回值。

    最后,如果你的线程有问题,你可以调用Kill函数终止线程执行。如果线程中使用了mutex,那么kill之后,mutex可能处于locked状态,这可能导致其它线程阻塞。


    Linux下实现 

    JThread私有成员

    class JThread
    {
    public:
    	JThread();
    	virtual ~JThread();
    // ...
    protected:
    	void ThreadStarted();
    private:
    //...
    	static void *TheThread(void *param);	
    	pthread_t threadid;
    
    	void *retval;
    	bool running;
    	
    	JMutex runningmutex;
    	JMutex continuemutex,continuemutex2;
    	bool mutexinit;
    };

    具体实现如下:

    JThread::JThread()
    {
    	retval = NULL;
    	mutexinit = false;
    	running = false;
    }
    
    JThread::~JThread()
    {
    	Kill();
    }
    
    int JThread::Start()
    {
    	int status;
    
    	//init runningmutex, continuemutex, continuemutex2
    	if (!mutexinit)
    	{
    		if (!runningmutex.IsInitialized())
    		{
    			if (runningmutex.Init() < 0)
    				return ERR_JTHREAD_CANTINITMUTEX;
    		}
    		if (!continuemutex.IsInitialized())
    		{
    			if (continuemutex.Init() < 0)
    				return ERR_JTHREAD_CANTINITMUTEX;
    		}
    		if (!continuemutex2.IsInitialized())
    		{
    			if (continuemutex2.Init() < 0)
    				return ERR_JTHREAD_CANTINITMUTEX;
    		}
    		mutexinit = true;
    	}
    	
    	runningmutex.Lock();
    	if (running)
    	{
    		runningmutex.Unlock();
    		return ERR_JTHREAD_ALREADYRUNNING;
    	}
    	runningmutex.Unlock();
    	
    	pthread_attr_t attr;
    	pthread_attr_init(&attr);
    	pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);//detached状态的线程,在结束的时候,会自动释放该线程所占用的资源。
    	
    	continuemutex.Lock();
    	status = pthread_create(&threadid,&attr,TheThread,this);  //创建线程,在这里 将会有两个线程分支, main thread和执行用户代码的子线程t	
    	pthread_attr_destroy(&attr);
    	if (status != 0)
    	{ // 线程创建失败
    		continuemutex.Unlock();
    		return ERR_JTHREAD_CANTSTARTTHREAD;
    	}
    	
    	/* Wait until 'running' is set */
    	
    	runningmutex.Lock();			
    	while (!running)
    	{
    		runningmutex.Unlock();
    		
    		struct timespec req,rem;
    
    		req.tv_sec = 0;
    		req.tv_nsec = 1000000;
    		nanosleep(&req,&rem);
    
    		runningmutex.Lock();
    	}
    	runningmutex.Unlock();
    /*Line-M1*/	
    	continuemutex.Unlock();
    /*Line-M2*/	
    	continuemutex2.Lock(); // 主线程在此阻塞, 直到子线程调用了 ThreadStarted 方法
    	continuemutex2.Unlock();
    /*Line-M3*/
            return 0;
    }
    
    int JThread::Kill()
    {
    	runningmutex.Lock();			
    	if (!running)
    	{
    		runningmutex.Unlock();
    		return ERR_JTHREAD_NOTRUNNING;
    	}
    	pthread_cancel(threadid);
    	running = false;
    	runningmutex.Unlock();
    	return 0;
    }
    
    bool JThread::IsRunning()
    {
    	bool r;
    	
    	runningmutex.Lock();			
    	r = running;
    	runningmutex.Unlock();
    	return r;
    }
    
    void *JThread::GetReturnValue()
    {
    	void *val;
    	
    	runningmutex.Lock();
    	if (running)
    		val = NULL;
    	else
    		val = retval;
    	runningmutex.Unlock();
    	return val;
    }
    
    void *JThread::TheThread(void *param)
    {
    	JThread *jthread;
    	void *ret;
    	
    	jthread = (JThread *)param;
    	
    	jthread->continuemutex2.Lock();//continuemutex2加锁, 在Thread方法中调用ThreadStarted后解锁
    	jthread->runningmutex.Lock();
    	jthread->running = true; //线程开始运行,设置线程状态true
    	jthread->runningmutex.Unlock();
    /*Line-T1*/	
    	jthread->continuemutex.Lock();
    	jthread->continuemutex.Unlock();
    /*Line-T2*/
    	ret = jthread->Thread(); //调用 用户实现的方法
    
    	jthread->runningmutex.Lock();
    	jthread->running = false; //线程结束运行,设置线程状态false
    	jthread->retval = ret;
    	jthread->runningmutex.Unlock();
    
    	return NULL;
    }
    
    void JThread::ThreadStarted() // 参考TheThread方法
    {
    	continuemutex2.Unlock();
    /*Line-T3*/
    }
    


    假设主线程为m, 子线程为t。线程m在调用Start方法时,创建了子线程t。线程t执行TheThread方法, 而TheThread方法中调用了用户实现的方法Thread

    线程m和t共有3次同步的过程:

    • 第1次通过runningmutex同步线程的状态running变量, 此时线程m执行到Line-M1,线程t执行到Line-T1;
    • 第2次通过continuemutex再次同步线程, 此时线程m执行到Line-M2,线程t执行到Line-T2;
    • 第3次通过continuemutex2同步线程, 此时线程m执行到Line-M3并返回,线程t执行到ThreadStarted方法中的Line-T3。显然,若用户不在Thread方法中调用ThreadStarted方法, 主线程m将阻塞,即使子线程结束也不会返回。


    Windows下实现

    windows下的实现与Linux下实现类似,不同的是创建线程,终止线程的方法不一样。在Windows下采用_beginthreadex创建线程,TerminateThread终止线程。执行流程这里不再重复。


    展开全文
  • jthread lite:C ++ 20的jthread(用于C ++ 11和更高版本) 婴儿期的作品。 彼得·费瑟斯通(Peter Featherstone)建议。 内容 用法示例 # include " nonstd/jthread.hpp " # include int main ( int argc, char ...
  • JTHREAD剖析

    千次阅读 2015-08-26 23:01:50
    1.JTHREAD介绍 实际项目中经常会涉及到多线程架构。为了给WINUX(Windows+Linux)平台提供一套相同的操作线程的接口,需要将平台上对线程操作的API封装成一个的通用类。JTHREAD即是这样的一个开源类库。 JTHREAD...

    1.JTHREAD介绍

    实际项目中经常会涉及到多线程架构。为了给WINUX(Windows+Linux)平台提供一套相同的操作线程的接口,需要将平台上对线程操作的API封装成一个的通用类。JTHREAD即是这样的一个开源类库。

    JTHREAD是很简单的,主要包含JThread类和JMutex类,它们分别代表一个线程和一个互斥体,互斥体是为了同步多线程通信。该开发包作了简单的跨平台实现,对于*NIX平台调用pthread库,对于Windows平台调用Win32 Theads库。

    本文基于JTHREAD库源码做简单剖析,以对前面线程控制、线程同步等议题实做演练。

    按照惯例,对于返回int类型值的函数,若返回大于等于0的值表示成功,负值表示出错。

     

    2.JMutex

    2.1 JMutex

    下面是类JMutex的定义。

    1. class JMutex  
    2. {  
    3. public:  
    4.     JMutex();  
    5.     ~JMutex();  
    6.   
    7.     int Init();  
    8.     int Lock();  
    9.     int Unlock();  
    10.     bool IsInitialized() { return initialized; }  
    11.   
    12. private:  
    13.   
    14. #if (defined(WIN32) || defined(_WIN32_WCE))  
    15. #ifdef JMUTEX_CRITICALSECTION  
    16.     CRITICAL_SECTION mutex; // 临界区对象  
    17. #else // Use standard mutex  
    18.     HANDLE mutex;           // 互斥内核对象  
    19. #endif // JMUTEX_CRITICALSECTION  
    20. #else // pthread mutex  
    21.     pthread_mutex_t mutex;  
    22. #endif // WIN32  
    23.   
    24.     bool initialized;  
    25. };  

            其数据成员根据平台区分。对于Windows系统(Win32或WinCE),若定义JMUTEX_CRITICALSECTION宏,则使用临界区对象CRITICAL_SECTION作为互斥体;否则,使用互斥内核对象(Mutex)作为互斥体。对于*NIX系统使用pthread_mutex_t作为互斥体。后面主要针对Windows系统解说,鉴于临界区旋转锁的高效性,建议使用JMUTEX_CRITICALSECTION

    int Init()完成互斥体的初始化;bool initialized跟踪初始化记录,确保只初始化一次。可调用bool IsInitialized()获取initialized的值,以判断是否已经初始化。

    int Init()中,如果定义了JMUTEX_CRITICALSECTION宏,则调用InitializeCriticalSection(&mutex)初始化临界区;否则mutex = CreateMutex(NULL,FALSE,NULL),创建互斥内核对象。

    Lock()/Unlock()为同步加解锁操作。Lock()内部体现为EnterCriticalSection(&mutex)进入临界区,或WaitForSingleObject(mutex,INFINITE)返回,可拥有互斥对象。Unlock()内部体现为LeaveCriticalSection(&mutex)离开临界区,或ReleaseMutex(mutex)释放拥有的互斥对象。

    构造函数JMutex()中初始化initialized = false;析构函数~JMutex()中DeleteCriticalSection(&mutex)删除临界区或CloseHandle(mutex)关闭互斥内核对象,释放互斥体资源。

    在你使用一个JMutex类的实例对象之前,你首先必须调用Init()函数执行初始化。通过检测IsInitialized()的返回值可以检测互斥体是否已经初始化。初始化之后,通过调用Lock()和Unlock()封闭需要同步的共享资源操作代码段。

    2.2 JMutexAutoLock

    下面是类JMutexAutoLock的定义。

    1. class JMutexAutoLock  
    2. {  
    3. public:  
    4.     JMutexAutoLock(JMutex &m) : mutex(m) { mutex.Lock(); }  
    5.     ~JMutexAutoLock() { mutex.Unlock(); }  
    6.   
    7. private:  
    8.     JMutex &mutex;  
    9. };  

    JMutexAutoLock需要传入一个JMutex对象的引用来构造,当然,要求该JMutex对象已经初始化。在构造函数中调用mutex.Lock()上锁,在析构函数中mutex.Unlock()解锁。

    JMutexAutoLock即所谓的自动锁,是对JMutex的自动管理,同步对象声明到对象生命周期结束之间的代码段(块)。它更容易实现线程安全,不用去担心什么时候为互斥体解锁。

    2.3 JMutex示例

    1. JMutex mutex;  
    2. mutex.Init();  
    3.   
    4. void DoSomeWork();  
    5.   
    6. void fun1()  
    7. {  
    8.     mutex.Lock();  
    9.     mutex.Unlock();  
    10.     DoSomeWork();  
    11.   
    12.     return;  
    13. }  
    14.   
    15. void fun2()  
    16. {  
    17.     mutex.Lock();  
    18.     DoSomeWork();  
    19.     mutex.Unlock();  
    20.       
    21.     return;  
    22. }  
    23.   
    24. void fun3()  
    25. {  
    26.     JMutexAutoLock AutoLock(mutex);  
    27.     DoSomeWork();  
    28.   
    29.     return;  
    30. }  

    (1)在fun1()中,mutex.Lock();和mutex.Unlock();之间没有任何代码,则此处只是等待外部使用mutex保护的代码块运行完毕。如果外部占用该mutex,则此处等待;如果外部已释放该mutex,则此处继续执行DoSomeWork()。这里纯粹是等待外部事件发生:后上锁的等待先上锁的解锁

    (2)fun2()和fun3()是等价的,都是为了保护DoSomeWork()过程中涉及到的共享资源操作。

    (3)在fun3()中,如果DoSomeWork()中途异常exit,则AutoLock不能正确析构,永远不会解锁。在此等待的后续线程(如果没有当掉)死锁。

     

    3.JThread

    下面是JThread类的定义。

    1. class JThread  
    2. {  
    3. public:  
    4.     JThread();  
    5.     virtual ~JThread();  
    6.   
    7.     int Start();  
    8.     int Kill();  
    9.     virtual void *Thread() = 0;  
    10.     bool IsRunning();  
    11.     void *GetReturnValue();  
    12.   
    13. protected:  
    14.     void ThreadStarted();  
    15.   
    16. private:  
    17.   
    18. #if (defined(WIN32) || defined(_WIN32_WCE))  
    19. #ifdef _WIN32_WCE  
    20.     DWORD threadid;  
    21.     static DWORD WINAPI TheThread(void *param);  
    22. #else  
    23. UINT threadid;  
    24. static UINT __stdcall TheThread(void *param);     
    25. #endif // _WIN32_WCE  
    26.     HANDLE threadhandle; //   
    27. #else // pthread type threads  
    28.     pthread_t threadid;  
    29.     static void *TheThread(void *param);  
    30. #endif // WIN32  
    31.   
    32.     void *retval;  
    33.     bool running;  
    34.       
    35.     JMutex runningmutex;  
    36.     JMutex continuemutex,  
    37.         continuemutex2;  
    38.   
    39.     bool mutexinit;  
    40. };  

    3.1JThread成员

    threadid为线程ID号,threadhandle为线程内核对象句柄。

    JThread类拥有三个JMutex对象成员,runningmutexcontinuemutexcontinuemutex2bool mutexinit为三个对象初始化状态记录,只有三个互斥对象都成功初始化,才能协作完成后续对线程流程的正确控制。

    TheThread(void *param)为通常意义上的线程入口函数,传递一个void*指针作为线程参数,该类静态入口传递JThread线程对象this指针。TheThread中调用Thread()完成特定的任务。我们姑且称TheThread()为线程壳(Shell),Thread()为线程核(Core)。

    bool running为线程运行状态;bool IsRunning()为对该状态属性的访问。

    void* retval为线程函数运行结果;void *GetReturnValue()为对该属性的访问。

    3.2JThread类剖析

    所谓同步是指多线程之间的同步,同一线程内部顺序执行不存在同步问题。JThread类中runningmutexcontinuemutexcontinuemutex2主要为了与它的创建线程同步。它的创建线程就是MyJThread对象实例声明代码所在的线程,也即调用JThread::Start()的线程。注意线程壳TheThread()是为线程入口函数,其中调用MyJThread对象实例(this)的Thread(),线程壳TheThread()和线程核Thread()代码运行于线程。因此,在Start()和TheThread()/Thread()间存在过程状态控制的同步问题。

    更一般的同步问题体现在MyJThread对象实例声明代码所在的线程与新建线程关于running状态及返回值retval的访问。runningmutex互斥体主要用来保护running状态变量的访问,当然retval的访问与running状态密切相关,只有运行完才有返回值。

    下面结合具体代码来分析Start()->TheThread()->Thread()的过程控制。

    1. int JThread::Start()  
    2. {  
    3.     if (!mutexinit)  
    4.     {  
    5.         // 初始化3个JMutex(代码略)  
    6.     }  
    7.       
    8.     runningmutex.Lock();  
    9.     if (running)  
    10.     {  
    11.         runningmutex.Unlock();  
    12.         return ERR_JTHREAD_ALREADYRUNNING;  
    13.     }  
    14.     runningmutex.Unlock();  
    15.       
    16.     continuemutex.Lock();  
    17.       
    18. #ifndef _WIN32_WCE  
    19.     threadhandle = (HANDLE)_beginthreadex(NULL,0,TheThread,this,0,&threadid);  
    20. #else  
    21.     threadhandle = CreateThread(NULL,0,TheThread,this,0,&threadid);  
    22. #endif // _WIN32_WCE  
    23.       
    24.     if (threadhandle == NULL)  
    25.     {  
    26.         continuemutex.Unlock();  
    27.         return ERR_JTHREAD_CANTSTARTTHREAD;  
    28.     }  
    29.       
    30.     /* Wait until 'running' is set */  
    31.     runningmutex.Lock();  
    32.     while (!running)  
    33.     {  
    34.         runningmutex.Unlock();  
    35.         Sleep(1);  
    36.         runningmutex.Lock();  
    37.     }  
    38.     runningmutex.Unlock();  
    39.       
    40.     continuemutex.Unlock();  
    41.       
    42.     continuemutex2.Lock();  
    43.     continuemutex2.Unlock();  
    44.       
    45.     return 0;  
    46. }  
    47.   
    48. #ifndef _WIN32_WCE  
    49. UINT __stdcall JThread::TheThread(void *param)  
    50. #else  
    51. DWORD WINAPI JThread::TheThread(void *param)  
    52. #endif // _WIN32_WCE  
    53. {  
    54.     JThread *jthread;  
    55.     void *ret;  
    56.       
    57.     jthread = (JThread *)param; // this  
    58.       
    59.     jthread->continuemutex2.Lock();  
    60.       
    61.     jthread->runningmutex.Lock();  
    62.     jthread->running = true// Thread is ready to run  
    63.     jthread->runningmutex.Unlock();  
    64.       
    65.     jthread->continuemutex.Lock();  
    66.     jthread->continuemutex.Unlock();  
    67.       
    68.     ret = jthread->Thread();  
    69.       
    70.     jthread->runningmutex.Lock();  
    71.     jthread->running = false// Thread run over  
    72.     jthread->retval = ret;  
    73.     CloseHandle(jthread->threadhandle); // Close Handle  
    74.     jthread->runningmutex.Unlock();  
    75.       
    76.     return 0;  
    77. }  
    78.   
    79. // Your own Thread implementation should call ThreadStarted immediately  
    80. void JThread::ThreadStarted()  
    81. {  
    82.     continuemutex2.Unlock();  
    83. }  

    continuemutex互斥体用来同步等待新线程调度,具体来说Start()中调用_beginthreadex创建新线程之前即上锁。然后,在runningmutex的保护下等待running被线程壳TheThread()置为trueStart()中的continuemutex才解锁,TheThread()继而执行线程核Thread()。

    新线程一调度(Start),即进入线程壳TheThread(),continuemutex2互斥体即上锁;Start()中continuemutex解锁,但仍未返回,还需等待continuemutex2解锁。在线程核Thread()中需立即调用ThreadStarted()解锁continuemutex2,此时Start()返回。也即在实际进入线程核Thread()执行时,Start()才返回。

    由以上分析可知:

    • runningmutex:父线程等待新线程调度,新线程调度时会设置信号量Signal(running = true),即runningmutex互斥体用来保护running状态变量的同步读写。
    • continuemutex:新线程等待父线程获知自己已调度运行,即continuemutex互斥体同步的是线程的创建到线程被调度(线程壳真正启动,running=true)过程。
    • continuemutex2:父线程等待新线程核执行,即continuemutex2互斥体同步的是线程被调度到线程核真正执行过程(Thread()->ThreadStarted())。此时,父线程真正启动了新线程(而不仅仅是创建成功),Start()才返回。

    3.3JThread类的使用说明

    因为含有未实现的纯虚函数virtual void *Thread() = 0,故JThread为抽象基类,无法直接声明创建JThread对象实例。在使用时,必须编写派生类实现Thread()接口,以完成特定的任务:classMyJThread : publicJThread这样,一个MyJThread类实际上只能完成一种特定的任务。如以上代码所述,往往为线程壳TheThread()传递JThread对象的this指针,以便线程核Thread()能访问派生类实例对象属性。记得在你自己的Thread()实现中实时调用ThreadStarted()使父线程Start返回。

    一个MyJThread对象管理完成特定任务的一个线程对象,其行为具有不可重入性。意即当MyJThread::Start()中开辟一条线程,mutexinitrunningmutexcontinuemutexcontinuemutex2runningretval等都是针对一次线程行为及状态的管理。如果在Start()没有返回之前,或者线程过程没有返回之前,试图再次调用该实例的Start()进行新线程的创建,则上述一套设施服务于两个线程对象,则容易造成管理上错乱。实际上JThread::Start()已经对运行状态作了检测,连续调用Start(),将导致ERR_JTHREAD_ALREADYRUNNING错误。当然Start()后,确保运行结束,可再次Start()开辟新的线程,以完成同类多任务,但此时已经丧失了多线程并发的初衷,因为实际上这里是一个线程跑完,才开另一个线程。

    对于同类多任务,往往声明创建多个MyJThread对象实例,然后Start()。在理想情况下,让线程核Thread()、线程壳TheThread()自然返回,以使其寿终正寝。迫不得已,可调用Kill()杀死线程。Kill()调用的是线程终结者TerminateThread(),如前所述,这种粗暴的行径将导致不良的后果,除非拥有此线程的进程终止运行,否则系统不会销毁这个线程的堆栈。当然,在继承的MyJThread,往往需要改进Kill()操作,以便作更优雅的控制退出。

    记住,一个MyJThread对象对应一个线程对象,你每Start一个MyJThread实例,就相当于创建一个线程。当然,只要你的MyJThread扩展到足够强壮,你也可以将同一级别的不同类任务在Thread()中作统一处理,这取决于你的业务分工强度。

    Start()理应让Thread()自然返回,Start()后通过调用IsRunning()函数可以检测线程是否在运行;若运行完毕(running=false),则可通过调用GetReturnValue()函数可以获取返回值。最后,你可以通过Kill()函数中止一个正在运行的线程。对于一个已经返回的线程,Kill()调用返回ERR_JTHREAD_NOTRUNNING

    3.4JThread应用实例:JRTPLIB中的RTPPollThread

    JTRPLIB中的RTP会话类RTPSession包含一个RTPPollThreadpollthread成员。RTPPollThread为JRTPLIB中的RTP会话响应线程,继承自JThread类。

    1. class RTPPollThread : private JThread  
    2. {  
    3. public:  
    4.     RTPPollThread(RTPSession &session, RTCPScheduler &rtcpsched);  
    5.     ~RTPPollThread();  
    6.     int Start(RTPTransmitter *trans);  
    7.     void Stop();  
    8. private:  
    9.     void *Thread();  
    10.       
    11.     bool stop;  
    12.     JMutex stopmutex;  
    13.     RTPTransmitter *transmitter;  
    14.       
    15.     RTPSession &rtpsession;  
    16.     RTCPScheduler &rtcpsched;  
    17. };  
    18. // 需要覆写实现的线程核  
    19. void *RTPPollThread::Thread()  
    20. {  
    21.     JThread::ThreadStarted();  
    22.       
    23.     bool stopthread;  
    24.       
    25.     stopmutex.Lock();  
    26.     stopthread = stop;  
    27.     stopmutex.Unlock();  
    28.     while (!stopthread)  
    29.     {  
    30.         int status;  
    31.           
    32.         rtpsession.schedmutex.Lock();  
    33.         rtpsession.sourcesmutex.Lock();  
    34.           
    35.         RTPTime rtcpdelay = rtcpsched.GetTransmissionDelay();  
    36.           
    37.         rtpsession.sourcesmutex.Unlock();  
    38.         rtpsession.schedmutex.Unlock();  
    39.           
    40.         if ((status = transmitter->WaitForIncomingData(rtcpdelay)) < 0)  
    41.         {  
    42.             stopthread = true;  
    43.             rtpsession.OnPollThreadError(status);  
    44.         }  
    45.         else  
    46.         {  
    47.             if ((status = transmitter->Poll()) < 0)  
    48.             {  
    49.                 stopthread = true;  
    50.                 rtpsession.OnPollThreadError(status);  
    51.             }  
    52.             else  
    53.             {  
    54.                 if ((status = rtpsession.ProcessPolledData()) < 0)  
    55.                 {  
    56.                     stopthread = true;  
    57.                     rtpsession.OnPollThreadError(status);  
    58.                 }  
    59.                 else  
    60.                 {  
    61.                     rtpsession.OnPollThreadStep();  
    62.                     stopmutex.Lock();  
    63.                     stopthread = stop;  
    64.                     stopmutex.Unlock();  
    65.                 }  
    66.             }  
    67.         }  
    68.     }  
    69.       
    70.     return 0;  
    71. }  

    RTPPollThread::Start()重载了基类的同名函数,作特定的初始化,调用JThread::Start()RTPPollThread::Stop()对JThread::Kill()进行了安全扩展,如果等5秒后依旧JThread::IsRunning(),才调用JThread::Kill()强制关闭。

    如果定义了RTP_SUPPORT_THREAD宏,则RTPSession支持多线程响应会话,usepollthread = true。在RTPSession::Create()中调用RTPSession::InternalCreate(),其中中创建线程(对象)。

    1. int RTPSession::InternalCreate(const RTPSessionParams &sessparams);  
    2. {  
    3.     // Do thread stuff if necessary  
    4.     if (usingpollthread)  
    5.     {  
    6.         // ……  
    7.         pollthread = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPPOLLTHREAD) RTPPollThread(*this,rtcpsched);  
    8.         if (pollthread == 0)  
    9.         {  
    10.             // ……  
    11.         }  
    12.         if ((status = pollthread->Start(rtptrans)) < 0)  
    13.         {  
    14.         }  
    15.     }  
    16. }  

      RTPPollThread::Thread()线程核处理具体的RTCP/RTP通信会话。在RTPSession::ProcessPolledData中调用RTPSessionSources::ProcessRawPacketRTPSessionSources::ProcessRawPacket中判断包的类型是RTCP还是RTP,若是RTCP包,则ProcessRTCPCompoundPacketàOnRTCPCompoundPacket处理;若是RTP包,则ProcessRTPPacketàOnRTPPacket处理,从而完成RTCP/RTP通信。

    关于JRTPLIB的使用,参考《JRTPLIB@Conference DIY视频会议系统》。

     

    4.CWinThread简介

    CWinThread作为MFC的线程管理类,极具参考性,源码参阅Microsoft Visual Studio/VC98/MFC/SRC/THRDCORE.CPP。尽管其采用了面向对象的封装,但在实作时,通常按照_beginthreadex的方式调用AfxBeginThread传入线程函数地址和线程参数。内部对CWinThread对象作了自动化的管理。重点关注_AFX_THREAD_STARTUP结构中的hEventhEvent2是怎么样同步实现线程控制的。

    实际应用中,如果不需要过于严格的封装需求,仅需对线程参数(ID、HANDLE、THREADPROC、THREADPARAM)等做简单的封装,以期控制。例如Peercast中的classThreadInfo

    1. // Peercast/core/common/sys.h  
    2. #ifdef WIN32  
    3. typedef int (WINAPI *THREAD_FUNC)(ThreadInfo*);  
    4. typedef unsigned int THREAD_HANDLE;  
    5. #endif  
    6.   
    7. class ThreadInfo  
    8. {  
    9. public:  
    10.     ThreadInfo()  
    11.     {  
    12.         active = false;  
    13.         id = 0;  
    14.         func = NULL;  
    15.         data = NULL;  
    16.     }  
    17.   
    18.     void shutdown()  
    19.     {  
    20.         active = false;  
    21.         // sys->waitThread(this);  
    22.     }  
    23.   
    24.     volatile bool active;  // 是否有效  
    25.     THREAD_FUNC func;      // 线程运行函数  
    26.     int id;                    // 线程ID  
    27.     THREAD_HANDLE handle;  // 线程句柄  
    28.   
    29.     void *data;              // 线程参数  
    30. };  
    展开全文
  • JThread VS2010 工程

    2014-11-06 16:48:30
    jthread 1.3.1 vs2010 下工程 编译通过。
  • lib_jthread.7z

    2020-07-07 20:06:26
    windows平天下的JRTP的jthread库(lib,x64)。JRTP为一RTP协议的开源库,使用较为广泛,能够用了传输给予UDP的音视频包(H264,ACC等)。
  • jrtplib-jthread-lib-源码

    2021-07-12 08:11:19
    jrtplib-jthread-lib jrtplib-jtrhead在windows-x86平台编译的静态库 jrtplib版本 v3.9.1 jthread版本 v1.3.1
  • jthread.lib

    2009-05-27 10:57:07
    通过VC6.0直接编译jthread-1.2.1得到的jthread.lib。
  • Jrtplib3.7和Jthread1.2

    2014-02-15 11:50:00
    Jrtplib3.7和Jthread1.2
  • 转:JThread

    2018-10-02 07:32:13
    JThread The JThread package provides some classes to make use of threads easy on different platforms. The classes are actually rather simple wrappers around existing thread implementations. The curr...

    JThread

    The JThread package provides some classes to make use of threads easy on different platforms. The classes are actually rather simple wrappers around existing thread implementations.

    The current version is 1.3.3. You can take a look at the ChangeLog, or browse previous versions and development code at GitHub.

    Features

    The package contains classes JThread and JMutex, which (obviously) represent a thread and a mutex. For unix-like platforms, the class implementations use the pthread library. On an MS-Windows platform, native Win32 threads are used.

    What's the price?

    The library is totally FREE!

    Download

    The library itself:

    There is a manual included in the library, but you can also view it on-line in PDF format at jthread.readthedocs.io

    IMPORTANT: As of version 1.1.0, your own Thread function should call the function ThreadStarted immediately. The Start function blocks until that function has been called. This way, when the Start function returns, we can be really sure that our own Thread implementation is called.

    Copyright & disclaimer

    The following copyright notice and disclaimer applies to the library.

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    So basically, you can use the library in any way you like, as long as you leave the copyright and disclaimer in the sources.

    Contact

    If you have any questions, remarks, suggestions or you would simply like to tell me what you are using the library for (I'm always interested), you can send me an email at this address: jori.liesenborgs@gmail.com

    展开全文
  • jthread,jtrplib编译

    2021-06-01 10:21:13
    #windows下 使用cMake_gui图形界面工具编译即可,不需要额外配置 ...因为jrtplib添加jthread时需要依赖jthread编译的东西,我手动配置失败了,但按照默认生成路径就能找到并编译成功,于是没有研究失败原因 ##使用版本 j
  • jthread-1.2.1

    2008-06-17 12:29:06
    jthread是jrtsp必须的lib
  • jthread_vs_work

    2014-08-30 17:16:26
    带VS编译项目,无需CMAKE操作 jthread-1.2.1.rar
  • jthread、jrtplib编译成功的所有文件包 jrtblib-3.11.1 jrtblib-3.11.1-build
  • jrtplib和jthread

    2010-02-26 15:59:19
    编译好的jrtplib.lib 和 jthread.lib
  • jthread_jrtp_vs08

    2014-05-14 15:21:09
    开源库jthread jrtp vs2008编译,已经使用,可用
  • vs2013 win7 jrtplib和jthread库文件
  • jrtplib、jthread编译 vs

    2021-02-25 09:01:46
    3.编译jthread (1)创建构建构建目录 (2)打开cmake选择路径,点击configure (3)选择编译器,图中选的是vs2013 32位,64位的需要选择后面带win64的 (4)点击Generate,生成对应vs项目 (5)打开项目,可以...
  • jrtplib使用的jthread

    2011-04-01 15:09:03
    jrtplib使用的jthread库,实现了线程、锁等的跨平台封装.
  • VS2013 win7 jrtplib和jthread库文件
  • // C++20新线程 jthread 体验代码 // // 编译(编译本代码,-pedantic 不是必须的): // g++ -std=c++20 -Wall -pedantic -pthread -static-libstdc++ C++20_jthread.cpp -o C++20_jthread // // 要求GCC10及以上...
  • 编译好的 jrtplib3.9.0和jthread1.3.0库,把头文件和库文件路径设置好就可用了,省得自己编译麻烦,可参考我的博客:http://blog.csdn.net/jid_223/article/details/6858663
  • jthread 1.3.1

    2012-05-31 15:16:27
    配合jrtplib使用 ,最新的进程库 ,用于rtp协议实现
  • 分别下载jrtplib-3.7.1.tar.gz和jthread-1.2.1.tar.gz。下载地址为: http://research.edm.uhasselt.be/jori/jrtplib/jrtplib-3.7.1.tar.gz和 http://research.edm.uhasselt.be/jori/jthread/jthread-1.2.1.tar...
  • linux下的jrtplib和jthread

    2018-09-19 09:11:02
    这两天有个项目是 用RTP协议进行音视频的实时传输,目前暂用开源代码进行实现,发现用到jrtplib和jthread两个库,后者看到thread,很明显关于线程的,两者的关系自然联想到线程收发数据,但是一定要用到jthread吗,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,237
精华内容 494
关键字:

jthread