I wrote a timer class for my project. I used standard C++ function calls for it.
I want to create a timer (start, stop, pause, continue, reset) it and also pass it new timings.
If the timer fires before I stop it, I want to get a qnx pulse message on a given channel.
This is the header:
#ifndef TIMER_H_
#define TIMER_H_
#include <time.h>
#include <sys/neutrino.h>
#include "HWaccess.h"
#include "address.h"
#define MILLISECONDS_NANOSECONDS_CONV 1000000
#define SECONDS_MILLISECONDS_CONV 1000
class Timer {
public:
/**
* Constructor creates a new timer, attaches to the given
* channel.
* Does not start timer!
*
* #param chid
* #param seconds
* #param milliseconds
* #param msg
*/
Timer(int chid, int sec, int msec, int msg);
/**
* Deletes timer after detach from channel
*/
virtual ~Timer();
/**
* Starts the timer
*/
void start();
/**
* Stops timer and resets it to initial values
*/
void stop();
/**
* Pauses the timer
*/
void pause();
/**
* Continues the timer
*/
void cont();
/**
* Resets the timer to initial values
*/
void reset();
/**
* Changes timer values to new given values and
* resets it
* Does not start the timer!
*
* #param seconds
* #param milliseconds
*/
void changeTime(int sec, int msec);
private:
/**
* Timer ID
*/
timer_t timerid;
/**
* Timerstruct for running timer
*/
struct itimerspec timer;
/**
* Timerstruct for backing up the running timer
*/
struct itimerspec backupTimer;
/**
* timer value: seconds
*/
int seconds;
/**
* timer value: milliseconds
*/
int miliSeconds;
/**
* Connection ID for timeout pulse
*/
int coid;
/**
* Event structure for timer if it fires
*/
struct sigevent event;
};
#endif /* TIMER_H_ */
...and the implementation:
#include "Timer.h"
Timer::Timer(int chid, int sec, int msec, int msg) {
if ((coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0)) == -1) {
printf("Timer: Error in ConnectAttach\n");
}
SIGEV_PULSE_INIT(&event, coid, SIGEV_PULSE_PRIO_INHERIT, PULSE_FROM_TIMER, msg/*Timer abgelaufen*/);
if (timer_create(CLOCK_REALTIME, &event, &timerid) == -1) {
printf("Timer: Error in timer_create()\n");
}
seconds = sec;
miliSeconds = msec;
reset();
}
Timer::~Timer() {
if (ConnectDetach(coid) == -1) {
printf("Timer: Error in ConnectDetach\n");
}
if (timer_delete(timerid) == -1) {
printf("Timer: Error in timer_delete()\n");
}
}
void Timer::start() {
if(timer_settime(timerid, 0, &timer, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::stop() {
// stop timer
timer.it_value.tv_sec = 0;
timer.it_value.tv_nsec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_nsec = 0;
if(timer_settime(timerid, 0, &timer, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
// reset it
reset();
}
void Timer::pause() {
timer.it_value.tv_sec = 0;
timer.it_value.tv_nsec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_nsec = 0;
// backup running timer values
if(timer_gettime(timerid, &backupTimer) == -1){
printf("Timer: Error in timer_gettime()\n");
}
// disarm
if(timer_settime(timerid, 0, &timer, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::cont() {
// recover old values
timer = backupTimer;
// Arm timer
if(timer_settime(timerid, 0, &timer, NULL) == -1) {
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::reset(){
timer.it_value.tv_sec = seconds;
timer.it_value.tv_nsec = miliSeconds * MILLISECONDS_NANOSECONDS_CONV;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_nsec = 0;
}
void Timer::changeTime(int sec, int msec){
seconds = sec;
miliSeconds = msec;
reset();
}
1) Can I set the timer struct's values to zero (to stop the timer) and backup the values in another back struct the way I am doing it? Or is the running timer decremented in the timer struct?
2) Can i easily restore the old timer values with a simple timer = backupTimer?
3) And finally, if I create and start a timer in a function, something like this:
void coolClass::interestingFunction() {
//do other time consuming stuff here...
Timer timer(chid, 10, 0);
timer.start();
}
... then the timer is created on the stack and when I exit this function (and its variables etc.) are no longer valid. Will the timer still count down and fire my pulse? Or will I have to use a classifier in my header file for this timer?
Ok i fixed all my problems ;>
if some1 is interested in how, heres the modified code:
#include "Timer.h"
Timer::Timer(int chid, int sec, int msec, int msg) {
if ((coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0)) == -1) {
printf("Timer: Error in ConnectAttach\n");
}
SIGEV_PULSE_INIT(&event, coid, SIGEV_PULSE_PRIO_INHERIT, PULSE_FROM_TIMER, msg/*Timer abgelaufen*/);
if (timer_create(CLOCK_REALTIME, &event, &timerid) == -1) {
printf("Timer: Error in timer_create()\n");
}
seconds = sec;
miliSeconds = msec;
reset();
}
Timer::~Timer() {
if (ConnectDetach(coid) == -1) {
printf("Timer: Error in ConnectDetach\n");
}
if (timer_delete(timerid) == -1) {
printf("Timer: Error in timer_delete()\n");
}
}
void Timer::start() {
//TODO running flag, wg doppelt pause / continue
if(timer_settime(timerid, 0, &timer, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::stop() {
// Stoppe den Timer
if(timer_settime(timerid, 0, NULL, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
// Zuruecksetzen
reset();
}
void Timer::pause() {
// disarm (da erster Wert NULL)
if(timer_settime(timerid, 0, NULL, &backupTimer) == -1){
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::cont() {
// Arm, da Werte im struct wieder != 0
if(timer_settime(timerid, 0, &backupTimer, NULL) == -1) {
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::reset(){
timer.it_value.tv_sec = seconds;
timer.it_value.tv_nsec = miliSeconds * MILLISECONDS_NANOSECONDS_CONV;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_nsec = 0;
}
void Timer::changeTime(int sec, int msec){
seconds = sec;
miliSeconds = msec;
reset();
}
Related
I'm developing a mmorpg with iocp sockets.When im testing with my client simulator , after 70-80 connection , writing operation at socket worker thread slowing down than users get lagged.
This is my worker thread ;
typedef void(*OperationHandler)(Socket * s, uint32 len);
void HandleReadComplete(Socket * s, uint32 len);
void HandleWriteComplete(Socket * s, uint32 len);
void HandleShutdown(Socket * s, uint32 len);
static OperationHandler ophandlers[] =
{
&HandleReadComplete,
&HandleWriteComplete,
&HandleShutdown
};
uint32 THREADCALL SocketMgr::SocketWorkerThread(void * lpParam){
SocketMgr *socketMgr = (SocketMgr *)lpParam;
HANDLE cp = socketMgr->GetCompletionPort();
DWORD len;
Socket * s = nullptr;
OverlappedStruct * ov = nullptr;
LPOVERLAPPED ol_ptr;
while (socketMgr->m_bWorkerThreadsActive)
{
if (!GetQueuedCompletionStatus(cp, &len, (LPDWORD)&s, &ol_ptr, INFINITE))
{
if (s != nullptr)
s->Disconnect();
continue;
}
ov = CONTAINING_RECORD(ol_ptr, OverlappedStruct, m_overlap);
if (ov->m_event == SOCKET_IO_THREAD_SHUTDOWN)
{
delete ov;
return 0;
}
if (ov->m_event < NUM_SOCKET_IO_EVENTS)
ophandlers[ov->m_event](s, len);
}
return 0;}
This is Write Complete event handler;
void HandleWriteComplete(Socket * s, uint32 len)
{
if (s->IsDeleted()) {
return;
}
s->m_writeEvent.Unmark();
s->BurstBegin(); // Lock
s->GetWriteBuffer().Remove(len);
TRACE("SOCK = %d removed = %d",s->GetFd(),len);
if (s->GetWriteBuffer().GetContiguousBytes() > 0) {
s->WriteCallback();
}
else {
s->DecSendLock();
}
s->BurstEnd(); // Unlock
}
WriteCallBack function ;
void Socket::WriteCallback()
{
if (IsDeleted() || !IsConnected()) {
return;
}
// We don't want any writes going on while this is happening.
Guard lock(m_writeMutex);
if(writeBuffer.GetContiguousBytes())
{
DWORD w_length = 0;
DWORD flags = 0;
// attempt to push all the data out in a non-blocking fashion.
WSABUF buf;
buf.len = (ULONG)writeBuffer.GetContiguousBytes();
buf.buf = (char*)writeBuffer.GetBufferStart();
m_writeEvent.Mark();
m_writeEvent.Reset(SOCKET_IO_EVENT_WRITE_END);
TRACE("\n SOCK = %d aslında giden = %X THREADID = %d", GetFd(), buf.buf[4],GetCurrentThreadId());
int r = WSASend(m_fd, &buf, 1, &w_length, flags, &m_writeEvent.m_overlap, 0);
if (r == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
{
m_writeEvent.Unmark();
DecSendLock();
Disconnect();
}
}
else
{
// Write operation is completed.
DecSendLock();
}
}
this is stuffs about mutexes ;
public:
/* Atomic wrapper functions for increasing read/write locks */
INLINE void IncSendLock() { Guard lock(m_writeMutex); ++m_writeLock; }
INLINE void DecSendLock() { Guard lock(m_writeMutex);
--m_writeLock; }
INLINE bool HasSendLock() {Guard lock(m_writeMutex); return (m_writeLock != 0); }
INLINE bool AcquireSendLock()
{
Guard lock(m_writeMutex);
if (m_writeLock != 0)
return false;
++m_writeLock;
return true;
}
private:
// Write lock, stops multiple write events from being posted.
uint32 m_writeLock;
std::recursive_mutex m_writeLockMutex;
This is read event handler;
void HandleReadComplete(Socket * s, uint32 len)
{
if (s->IsDeleted())
return;
s->m_readEvent.Unmark();
if (len)
{
s->GetReadBuffer().IncrementWritten(len);
s->OnRead();
s->SetupReadEvent();
}
else
{
// s->Delete(); // Queue deletion.
s->Disconnect();
}
}
OnRead function ;
void KOSocket::OnRead()
{
Packet pkt;
for (;;)
{
if (m_remaining == 0)
{
if (GetReadBuffer().GetSize() < 5) {
//TRACE("pkt returnzzz GetFd %d", GetFd());
return; //check for opcode as well
}
uint16 header = 0;
GetReadBuffer().Read(&header, 2);
//printf("header : %X", header);//derle at k
if (header != 0x55AA)
{
TRACE("%s: Got packet without header 0x55AA, got 0x%X\n", GetRemoteIP().c_str(), header);
goto error_handler;
}
GetReadBuffer().Read(&m_remaining, 2);
if (m_remaining == 0)
{
TRACE("%s: Got packet without an opcode, this should never happen.\n", GetRemoteIP().c_str());
goto error_handler;
}
}
if (m_remaining > GetReadBuffer().GetAllocatedSize())
{
TRACE("%s: Packet received which was %u bytes in size, maximum of %u.\n", GetRemoteIP().c_str(), m_remaining, GetReadBuffer().GetAllocatedSize());
goto error_handler;
}
if (m_remaining > GetReadBuffer().GetSize())
{
if (m_readTries > 4)
{
TRACE("%s: packet fragmentation count is over 4, disconnecting as they're probably up to something bad\n", GetRemoteIP().c_str());
goto error_handler;
}
m_readTries++;
return;
}
uint8 *in_stream = new uint8[m_remaining];
m_readTries = 0;
GetReadBuffer().Read(in_stream, m_remaining);
uint16 footer = 0;
GetReadBuffer().Read(&footer, 2);
if (footer != 0xAA55
|| !DecryptPacket(in_stream, pkt))
{
TRACE("%s: Footer invalid (%X) or failed to decrypt.\n", GetRemoteIP().c_str(), footer);
delete [] in_stream;
goto error_handler;
}
delete [] in_stream;
// Update the time of the last (valid) response from the client.
m_lastResponse = UNIXTIME2;
//TRACE("pkt:%d GetFd %d", pkt.GetOpcode(), GetFd());
if (!HandlePacket(pkt))
{
TRACE("%s: Handler for packet %X returned false\n", GetRemoteIP().c_str(), pkt.GetOpcode());
#ifndef _DEBUG
goto error_handler;
#endif
}
m_remaining = 0;
}
//TRACE("pkt return11 GetFd %d", GetFd());
return;
error_handler:
Disconnect();
}
and this is how my server sends to packet to clients ;
BurstBegin();
//TRACE("\n SOCK = %d FREE SPACE = %d ",GetFd(),GetWriteBuffer().GetSpace()/*, GetWriteBuffer().m_writeLock*/);
if (GetWriteBuffer().GetSpace() < size_t(len + 6))
{
size_t freespace = GetWriteBuffer().GetSpace();
BurstEnd();
Disconnect();
return false;
}
TRACE("\n SOCK = %d gitmesi gereken paket = %X THREADID = %d", GetFd(), out_stream[0],GetCurrentThreadId());
r = BurstSend((const uint8*)"\xaa\x55", 2);
if (r) r = BurstSend((const uint8*)&len, 2);
if (r) r = BurstSend((const uint8*)out_stream, len);
if (r) r = BurstSend((const uint8*)"\x55\xaa", 2);
if (r) BurstPush();
BurstEnd();
The number of Worker threads according to processor number;
for(int i = 0; i < numberOfWorkerThreads; i++)
{
m_thread[i] = new Thread(SocketWorkerThread, this);
}
The server which i tested on it has Intel XEON E5-2630 v3 2.40 ghz (2 processor)
Can you guys help me about how can i improve performance ? For ex: when the client moves in the map per 1.5 second that sends to move packet to server and if it success server sends to every client in that region that move packet.
When client count increasing server starts to slow down to send back to packets to clients.My write buffer filling fully (it's capacity 16384 bytes) cause server couldn't send packets inside of the writebuffer.
So in my current RTOS code for mbed I have a timer that counts down from 3 minutes displayed in the format of minutes:seconds.I need to implement way so when the time gets to under a minute, the time is displayed in hundredths of a second, such as 59:59. How would I do that?
Here is my current code (the relevant code for displaying time is under void lcd_func (void const *args)):
#include "mbed.h"
#include "cmsis_os.h"
#include "scoreboard.h"
#define deb 180
C12832 lcd(p5, p7, p6, p8, p11);
LM75B sensor(p28,p27);
InterruptIn By1(p15); // Up on the Joystick
InterruptIn By2(p16); // Right on the Joystick
InterruptIn By3(p12); // Down on the Joystick
InterruptIn Team(p14); // Push on the Joystick
InterruptIn Play(p13); // Left to activate clock
// declaration of IDs handle for various threads
osThreadId score_ID, LCD_ID, time_ID, temp_ID;
// definition of the thread
osThreadDef(score_func, osPriorityNormal, DEFAULT_STACK_SIZE);
osThreadDef(lcd_func, osPriorityNormal, DEFAULT_STACK_SIZE);
osThreadDef(time_func, osPriorityNormal, DEFAULT_STACK_SIZE);
osThreadDef(temp_func, osPriorityNormal, DEFAULT_STACK_SIZE);
// message from ISrs
osMessageQDef(queue, 1, uint32_t);
osMessageQId(queue_ID);
// service routines for Joystick Up, Right and Down
void By1_isr() {osMessagePut(queue_ID, 1, 0);}
void By2_isr() {osMessagePut(queue_ID, 2, 0);}
void By3_isr() {osMessagePut(queue_ID, 3, 0);}
void Team_isr();
void Time_isr();
Timer t;
int minutes,seconds,zero,faults;
int main()
{
t.start();//start the timer
By1.rise(&By1_isr);
By2.rise(&By2_isr);
By3.rise(&By3_isr);
Team.rise(&Team_isr);
Play.rise(&Time_isr);
queue_ID = osMessageCreate(osMessageQ(queue), NULL);
score_ID = osThreadCreate(osThread(score_func), NULL);
LCD_ID = osThreadCreate(osThread(lcd_func), NULL);
time_ID = osThreadCreate(osThread(time_func), NULL);
temp_ID = osThreadCreate(osThread(temp_func), NULL);
}
void Team_isr()
{
if(t.read_ms() > deb) {
score.h0v1 = !score.h0v1;
osSignalSet(LCD_ID, 0x2);
t.reset();
}
}
void Time_isr()
{
if (score.running == 0)
{
score.running = 1;
}
else
{
faults++;
score.running = 0;
}
osSignalSet(time_ID, 0x3);
}
void Timer1_Update (void const *args)
{
score.time_count -= 1;
osSignalSet(LCD_ID, 0x2);
}
void Destroy(float val)
{
osThreadTerminate(time_ID);
osThreadTerminate(score_ID);
osThreadTerminate(LCD_ID);
lcd.cls();
lcd.locate(0,3);
lcd.printf("Gamed Terminated!\n");
lcd.printf("(temperature reached %2.1f)\n", val);
osThreadTerminate(temp_ID);
}
void score_func (void const *args)
{
score.h0v1 = 0; // home by default
score.time_count = 180;
score.home_count = 0;
score.visitors_count = 0;
uint32_t val;
while (1) {
osEvent score_sig = osMessageGet(queue_ID, osWaitForever);
if (score_sig.status == osEventMessage)
val = score_sig.value.v;
if (score.h0v1 == 0)
score.home_count += val;
else
score.visitors_count += val;
osSignalSet(LCD_ID, 0x2);
}
}
void lcd_func (void const *args)
{
while(1) {
minutes=score.time_count/60;
seconds=score.time_count%60;
if (seconds<10)
{
lcd.cls();
lcd.locate(0,3);
lcd.printf("Time remaining: %2d:%d%d\n",minutes,zero,seconds);
}
else{
lcd.cls();
lcd.locate(0,3);
lcd.printf("Time remaining: %2d:%2d\n",minutes,seconds);}
if (score.h0v1 == 0)
lcd.printf("*Home: %2d Visitors: %2d\n",
score.home_count, score.visitors_count);
else
lcd.printf(" Home: %2d *Visitors: %2d\n",
score.home_count, score.visitors_count);
osSignalWait(0x2, osWaitForever);
}
}
void time_func (void const *args)
{
osTimerDef (Timer1, Timer1_Update);
osTimerId Timer1_ID;
// Activate time
Timer1_ID = osTimerCreate (osTimer(Timer1), osTimerPeriodic, NULL);
while(1) {
osSignalWait(0x3, osWaitForever);
if (score.running == 0)
osTimerStop (Timer1_ID);
else
osTimerStart (Timer1_ID, 1000UL);
}
}
void temp_func (void const *args)
{
float temp;
if (sensor.open()) {
sensor.alertTemp(40.0);
while (1) {
temp = (float)sensor.temp();
if (temp > 30.0)
Destroy(temp);
osDelay(5000);
}
}
else
osThreadTerminate(temp_ID);
}
Change your timer to decrement every 100th and start at 18000. Then:
minutes = score.time_count / 6000;
seconds = (score.time_count % 6000) / 100 ;
hundredths = score.time_count % 100 ;
...
if( minutes == 0 )
{
lcd.printf( "Time remaining: 00:%2d:%2d\n", seconds, hundredths ) ;
}
else
{
lcd.printf( "Time remaining: %2d:%2d:00\n", minutes, seconds ) ;
}
Okay, so I've an assignment with threads.I'm suppose to change the current running threads each period of time, let's say a second. First of all I've created a Thread class:
typedef unsigned long address_t;
#define JB_SP 6
#define JB_PC 7
#define STACK_SIZE (4096)
using namespace std;
class Thread{
public:
enum State{
BLOCKED,
READY,
RUNNING
};
Thread(int tid, void(*f)(void), int stack_size) :
tid(tid), stack_size(stack_size){
address_t sp, pc;
sp = (address_t)stack + STACK_SIZE - sizeof(address_t);
pc = (address_t)f;
sigsetjmp(env, 1);
(env->__jmpbuf)[JB_SP] = translate_address(sp);
(env->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&env->__saved_mask);
state = READY;
quantums = 0;
}
Thread (){}
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%fs:0x30,%0\n"
"rol $0x11,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
State get_state() const
{
return state;
}
void set_state(State state1)
{
state = state1;
}
int get_id() const
{
return tid;
}
pthread_t& get_thread()
{
return thread;
}
sigjmp_buf& get_env()
{
return env;
}
void raise_quantums()
{
quantums ++;
}
int get_quantums()
{
return quantums;
}
int add_to_sync(int tid)
{
sync.push_back(tid);
}
bool appear_in_sync_list(int tid)
{
return (find(sync.begin(), sync.end(), tid) != sync.end());
}
private:
vector<int> sync;
int quantums;
State state;
char stack[STACK_SIZE];
sigjmp_buf env;
pthread_t thread;
int tid;
int stack_size;
};
I've this function which changes threads:
void running_thread(int sigNum)
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_SETMASK, &set, NULL);
total_quantum ++;
if (currentThread.get_state() == Thread::RUNNING)
{
Thread& t = ready_threads.back();
ready_threads.pop_back();
currentThread.set_state(Thread::READY);
ready_threads.push_back(currentThread);
sigsetjmp(currentThread.get_env(), 1);
currentThread = t;
t.raise_quantums();
siglongjmp(currentThread.get_env(), 1);
}
if (currentThread.get_state() == Thread::BLOCKED)
{
Thread &t = ready_threads.back();
ready_threads.pop_back();
currentThread.set_state(Thread::BLOCKED);
blocked_threads.push_back(currentThread);
sigsetjmp(currentThread.get_env(), 1);
currentThread = t;
t.raise_quantums();
siglongjmp(currentThread.get_env(), 1);
}
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_UNBLOCK, &set, NULL);
}
It actually doesn't matter what it do, my problem is that it isn't even called.
My program first call this function:
int clock_set()
{
int seconds = quantum / SECOND;
int usecs = quantum - seconds*SECOND;
timer.it_value.tv_sec = seconds;
timer.it_value.tv_usec = usecs;
timer.it_interval.tv_sec = seconds;
timer.it_interval.tv_usec = usecs;
struct sigaction sa;
sa.sa_handler = &running_thread;
if (sigaction(SIGVTALRM, &sa,NULL) < 0) {
cerr << "system error: sigaction error.";
return FAILURE;
}
// Start a virtual timer. It counts down whenever this process is executing.
if (setitimer (ITIMER_VIRTUAL, &timer, NULL)) {
cerr << "system error: setitimer error.";
return FAILURE;
}
return SUCCESS;
}
Basically I was trying to make running_thread get activate each second, so I Was using sigaction and sa_handler.
This is my main function:
int main()
{
uthread_init(1000000) // Initiliaze variable 'quantum' to be a second, this function also calls clock_set
uthread_spawn(&g); // Creating a thread object with function g inserting it to ready_threads vector and to threads vector
uthread_spawn(&f); // creating a thread object with function f inserting it to ready_threads vector and to threads vector
}
The vector "ready_threads" has 2 threads in it.
Why doesn't it call running_thread?
I've tried to use SDL_GetTimer() to make action after passing 1000ms using this piece of code:
while(1)
{
int tajmer;
int czas = SDL_GetTicks();
tajmer = SDL_GetTicks() - czas;
if(tajmer > 1000)
{
MoveUp();
czas = SDL_GetTicks();
}
}
But it causes my program to crash. Any ideas why, or how to implement simple timer correctly?
Every time the loop runs, czas is updated to the current time.
Solution: Move it out of the loop.
int czas = SDL_GetTicks();
while(1)
{
int tajmer;
tajmer = SDL_GetTicks() - czas;
if(tajmer > 1000)
{
MoveUp();
czas = SDL_GetTicks();
}
}
However what you are trying to accomplish could possibly be done in a better way using built in timers:
http://wiki.libsdl.org/SDL_AddTimer
Edit:
Example using SDL_AddTimer.
Uint32 my_callbackfunc(Uint32 interval, void *param);
int main() {
... // don't forget to SDL_Init
...
SDL_AddTimer(1000, my_callbackfunc, NULL);
...
}
Uint32 my_callbackfunc(Uint32 interval, void *param)
{
MoveUp();
return(1000); // or however long to wait before my_callbackfunc should run.
}
If you are currently using classes and want to call a class's method called MoveUp() then perhaps:
class example {
...
void start_moving() {
SDL_AddTimer(1000, my_callbackfunc, (void*)this);
}
...
public void MoveUp() {
...
}
}
Uint32 my_callbackfunc(Uint32 interval, void *param) {
((example*)param)->MoveUp();
return (1000);
}
Continuing on Yujin Wus answer you can also do something like this.
int timer = 0;
int ticks = SDL_GetTicks();
while(true)
{
timer += SDL_GetTicks() - ticks;
ticks = SDL_GetTicks();
if(timer >= 1000)
{
timer -= 1000;
MoveUp();
}
}
Or something like this
const int DELAY = 1000;
int timer = SDL_GetTicks() + DELAY;
while(true)
{
if(timer - SDL_GetTicks() <= 0)
{
timer += DELAY;
MoveUp();
}
}
I am writing code for Linux on a x86-64 machine. It is working perfectly on x86-64, but I ported the same code to an ARM based device and now I am getting error: Invalid argument for timer code. Following is my timer code:
/**
* FUNCTION NAME : startRetryCount
* #brief start the retry count
* #param isAuth: if true start retry for Auth message else for Normal message
* #return true if success and false if not
*/
bool startRetryCount(bool isAuth)
{
m_RetryAuth = isAuth;
stopRetryCount();
struct sigevent sigev;
struct itimerspec itval;
struct itimerspec oitval;
struct sigaction sigact;
if(sigemptyset(&sigact.sa_mask) == -1)
{
printLog(LOG_ERROR,"[%s:%d#%s] <<<< sigemptyset >>>> : %s\n",
__FILE__,__LINE__,__func__,strerror(errno));
}
sigact.sa_flags = SA_SIGINFO;
sigact.sa_sigaction = signalHandler;
m_RetryCount = ConfigureManager_SingleTon::getInstance()->getRetryCount();
printLog(LOG_INFO,"**Retry Count Started**\n");
printLog(LOG_INFO,"Number of Retry Count:%d\n",m_RetryCount);
printLog(LOG_INFO,"Retry time is:%d\n",
ConfigureManager_SingleTon::getInstance()->getRetryTime());
// set up sigaction to catch signal
if (sigaction(SIGTIMER, &sigact, NULL) == -1)
{
printLog(LOG_ERROR,"[%s:%d#%s] <<<< time_settime >>>> : %s\n",
__FILE__,__LINE__,__func__,strerror(errno));
return false;
}
//Create the POSIX timer to generate signo
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = SIGRTMAX;
sigev.sigev_value.sival_int = RETRY_ID;
if (timer_create(CLOCK_REALTIME, &sigev, &m_RetryTimerId) == 0)
{
itval.it_value.tv_sec = ConfigureManager_SingleTon::getInstance()->getRetryTime();
itval.it_value.tv_nsec = 0L;
itval.it_interval.tv_sec = itval.it_value.tv_sec;
itval.it_interval.tv_nsec = itval.it_value.tv_nsec;
if (timer_settime(m_RetryTimerId, 0, &itval, &oitval) != 0)
{
Utility_SingleTon::printLog(LOG_ERROR,"[%s:%d#%s] <<<< time_settime >>>> %s\n",
__FILE__, __LINE__,__func__,strerror( errno ));
return false;
}
}
else
{
printLog(LOG_ERROR,"[%s:%d#%s] <<<< timer_create >>>> %s",
__FILE__, __LINE__,__func__,strerror( errno ));
return false;
}
return true;
}
/**
* FUNCTION NAME : stopRetryCount
* #brief stop the retry count
*/
voidstopRetryCount()
{
if(m_RetryTimerId != NULL)
{
if(timer_delete(m_RetryTimerId) != 0)
{
printLog(LOG_ERROR,"[%s:%d#%s] Timer delete error [%d]=%s\n",__FILE__, __LINE__,__func__,errno,strerror(errno));
}
m_RetryCount = 0;
m_RetryTimerId = NULL;
printLog(LOG_INFO,"Retry Timer Stopped!\n");
}
}
Print log of errors is:
[src/manager.cpp:686#stopRetryCount] Timer delete error [22]=Invalid argument
I have tried a lot to find what is bothering the ARM based device, but unfortunately I am not able to resolve the issues. Any help would be highly appreciated.
Edited:
To simulate my condition, I have created sample program, now I came to know that on mistral SAM-9 processor Timer and thread combinedly not working, If I start the timer in the main thread and if I tries to stop that timer through child thread, then it is giving that error. Here is the sample.cpp file source:
#include "devicetimer.h"
int DeviceTimer::counter = 0;
timer_t DeviceTimer::testTimer1Id = 0;
void DeviceTimer::timer1Stop()
{
if(testTimer1Id != 0)
{
if(timer_delete(testTimer1Id) == -1)
{
printf("Timer Delete Error\nError Number = %d\nError Message = %s\n",errno,strerror(errno));
exit(1);
}
else
{
printf("Timer Delete Successfully\n");
}
}
}
void DeviceTimer::signalHandler(int signo, siginfo_t* info, void* context)
{
if (signo == SIGTIMER)
{
printf("counter %d\n\n",++counter);
}
}
int DeviceTimer::timer1start()
{
struct sigevent sigev; //signal event struct
struct itimerspec itval;
struct itimerspec oitval;
struct sigaction sigact;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
sigact.sa_sigaction = signalHandler;
// set up sigaction to catch signal
if (sigaction(SIGTIMER, &sigact, NULL) == -1)
{
printf("time_settime error \n");
return -1;
}
//Create the POSIX timer to generate signo
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = SIGTIMER;
sigev.sigev_value.sival_int = 2;
if (timer_create(CLOCK_REALTIME, &sigev, &testTimer1Id) == 0)
{
itval.it_value.tv_sec = 1;
itval.it_value.tv_nsec = 0L;
itval.it_interval.tv_sec = itval.it_value.tv_sec;
itval.it_interval.tv_nsec = itval.it_value.tv_nsec;
if (timer_settime(testTimer1Id, 0, &itval, &oitval) != 0)
{
printf("Error in set time \n");
return -2;
}
}
else
{
printf("Error in creating timer \n");
return -3;
}
return 0;
}
void* DeviceTimer::threadFunction(void* data)
{
DeviceTimer *deviceTimer = (DeviceTimer *) data;
while(1)
{
printf(".\n");
usleep(100000);
if(counter > 25)
{
deviceTimer->timer1Stop();
break;
}
}
return NULL;
}
void DeviceTimer::startThread()
{
if(pthread_create(&m_Thread, NULL, DeviceTimer::threadFunction, this) != 0)
{
printf("Error in creating Thread\n");
exit(1);
}
}
int main()
{
DeviceTimer deviceTimer;
deviceTimer.timer1start();
deviceTimer.startThread();
while(1)
{
}
return 0;
}
And following is the output:
counter 26
Timer Delete Error
Error Number = 22
Error Message = Invalid argument
If anyone experinced the same problem then, please help me to resolve this issue.
Thanks & BR,
Yuvi
Make sure your timer ID is the proper type (timer_t). If you're accidentally using a different type, errors like these might happen since timer_delete() isn't able to recognize the ID.