【Android】如何在android下采用相對時間,實現超時等待的功能

一、函數功能說明


pthread_cond_timedwait 等待一個條件變量,或者超時就會返回

POSIX有兩種時鐘類型

1、CLOCK_REALTIME: 系統範圍內的實時時鐘,是個軟件時鐘,可以通過命令等方式修改該系統時間.
2、CLOCK_MONOTONIC:系統起機時到現在的時間,不能被設置和修改.

pthread_cond_timedwait()在沒有設置條件變量屬性的時候,默認用的是CLOCK_REALTIME軟件時間,
因此在極端情況下會出現實際等待的時間與設置的超時時間不同。
所以,對於linux的超時等待功能,最好是使用CLOCK_MONOTONIC進行實現,並且通過pthread_condattr_setclock實現。

而對於android系統而言,是不支持pthread_condattr_setclock,通過驗證可以採用函數pthread_cond_timedwait_monotonic實現。

下面直接給出代碼的實現功能。


二、超時等待功能


#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/times.h>
#include <unistd.h>
#include <time.h>

static pthread_mutex_t s_mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;

void PthreadAttr_Init(void);
unsigned long long getSysTime(void);
void waitTimeout(void);

void PthreadAttr_Init(void)
{
#if defined(ANDROID)

#else
	pthread_condattr_t cattr;
	int iRet = -1;
	iRet = pthread_condattr_init(&cattr);
	if (iRet != 0)
	{
		return;
	}	
	pthread_mutex_init(&s_mut, NULL);
	pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
	pthread_cond_init(&s_cond, &cattr);
	pthread_condattr_destroy(&cattr);
#endif
	return;
}

void waitTimeout(void)
{
	unsigned long long ullbefore = getSysTime();
	unsigned long long ullafter = 0;	
	
#if defined(ANDROID)

#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)  	// 支持ANDROID下NDK的編譯,採用相對時間
	struct timespec outtime;
	memset(&outtime, 0x00, sizeof(struct timespec ));
	clock_gettime(CLOCK_MONOTONIC, &outtime);
	outtime.tv_sec += 2;
	pthread_mutex_lock(&s_mut);
	pthread_cond_timedwait_monotonic(&s_cond,&s_mut, &outtime);
	pthread_mutex_unlock(&s_mut);
	ullafter = getSysTime();
	printf("####01 interval[%lld] ms\n", ullafter - ullbefore);
#else	//支持ANDROID下NDK的編譯,採用絕對時間
	struct timeval now;
	struct itmespec outtime;
	gettimeofday(&now, NULL);
	outtime.tv_sec = now..tv_sec + 3;
	outtime.tv_nsec = now.tv_usec * 1000;
	pthread_mutex_lock(&s_mut);
	pthread_cond_timedwait(&s_cond, &s_mut, &outtime);
	pthread_mutex_unlock(&s_mut);
    ullafter  = getSysTime();
	printf("####02 interval[%lld] ms\n", ullafter - ullbefore);
#endif	
	
#else  // 支持LINUX下的編譯,採用絕對時間
	struct timespec outtime;
	memset(&outtime, 0x00, sizeof(struct timespec ));
	clock_gettime(CLOCK_MONOTONIC, &outtime);	
	outtime.tv_sec += 4;
	pthread_mutex_lock(&s_mut);
	pthread_cond_timedwait(&s_cond, &s_mut, &outtime);
	pthread_mutex_unlock(&s_mut);
	ullafter  = getSysTime();
	printf("####03 interval[%lld] ms\n", ullafter - ullbefore);
#endif
	return;
}

unsigned long long getSysTime(void)
{
	unsigned long long  milliseconds = 0;

	struct tms t_tmsTime;
	clock_t t_CurTime;
    static int s_clks_per_sec = 0;

    if (s_clks_per_sec == 0)
    {
        s_clks_per_sec = sysconf(_SC_CLK_TCK);
    }

    if (s_clks_per_sec == 0)
    {
        return 0;
    }
    
	t_CurTime = times(&t_tmsTime);

    if (1000 % s_clks_per_sec == 0)
    {
        milliseconds = (1000 /s_clks_per_sec)*(unsigned long long )t_CurTime;//換算成毫秒
    }
    else 
    {
        milliseconds = 1000 *  (unsigned long long )t_CurTime/s_clks_per_sec;//換算成毫秒
    }

	return milliseconds;
}


int main(void)
{
	PthreadAttr_Init();
	waitTimeout();
	return 0;
}



編譯命令:

gcc test_ptthrad_conf_timewait_monotonic.c -o test_ptthrad_conf_timewait_monotonic -lpthread -lrt


linux下的測試結果:

####03 interval[4010] ms

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章