I'm trying to write a DNS server and I need the IP/name mappings to delete themselves after a given number of seconds. How can I accomplish that?

Thank you

Recommended Answers

All 6 Replies

In a timer thread do this:

class MyObject
{
public:
   ...
   void Destroy() {delete this;}
   ...
};

MyObject* obj = new MyObject;
// in a timer thread

obj.Destroy();

Obviously the possible solution depends on the general architecture of your application (and run-time environment). In standard C++ an object life time defined with regard to the only execution thread and it's not a real time.

Obviously the possible solution depends on the general architecture of your application (and run-time environment). In standard C++ an object life time defined with regard to the only execution thread and it's not a real time.

Hmm, i find this question very interesting, and as ArkM said, it's very run-time environment dependent...
I tried to implement a wrapper class that takes an dynamic allocated object and destroys it after X seconds. It uses the pthred library to create the timer in another thread

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

using namespace std;

class Exception {};

template < class T>
class ObjTimerWrapper
{
private:
	T* obj_;	

	int seconds_;

	pthread_mutex_t mutex;
	pthread_t timer;
	void DeleteObj()
	{
		pthread_mutex_lock( &mutex );
		delete obj_;
		obj_ = 0;
		pthread_mutex_unlock( &mutex );
	}

public:
	ObjTimerWrapper( T* obj, unsigned int seconds):obj_(obj), seconds_(seconds)
	{
		pthread_mutex_init( &mutex, 0 );
		pthread_create(&timer, NULL, ObjTimerWrapper::startTimer, (void*)this );		
	}

	~ObjTimerWrapper()
	{
		pthread_join( timer, 0 );
		pthread_mutex_destroy(&mutex);
		cout<<"destructor called"<<endl;
	}

	void Lock() { pthread_mutex_lock( &mutex ); }
	void UnLock() { pthread_mutex_unlock( &mutex ); }

	T* operator->() 
	{ 
		if ( ! obj_ ) throw Exception();
		return obj_; 
	}
	T* get() 
	{
		if ( ! obj_ ) throw Exception(); 
		return obj_; 
	}
	
	static void* startTimer(void * arg);
	
};

template < class T>
void *ObjTimerWrapper<T>::startTimer(void* arg)
{
	ObjTimerWrapper* p = (ObjTimerWrapper*)arg;
	
	sleep( p->seconds_);	
	
	p->DeleteObj();

	cout<<"timer expired, object destroyed-----------"<<endl;
	return 0;
}

class X
{
public:
	double x;
	void iterate();
	X( float xx ):x(xx){}
};

void X::iterate()
{
	for( int i = 0; i < 7; ++i )
	{
		sleep(1);
	}
	cout<<"rdy"<<endl;
}


int main ( int argc, char* argv[] )
{
	{
		ObjTimerWrapper<X> myobj( new X(0), 1 );
		myobj.Lock();
		myobj->iterate();
		myobj.UnLock();	
	}
	
	cout<<"end program"<<endl;	
}

ObjTimerWrapper contains the dynamically alocated object ( pointer to it is stored in T* obj_)

Well, what happenes is that the timer thread that runs
void *ObjTimerWrapper<T>::startTimer(void* arg)
issues sleeps for X secs and then destroys the contained object
The destructor of ObjTimerWrapper joines with the timer thread, so the object can not be destroyed before the seconds pass ( say if ObjTimerWrapper gets out of scope it will wait in it's destructor till the timer joins )

The real problem is sycronization.
What happens if you are currently working on the contained object and the timer thread tries to destroy it? the thing is i provided a mutex locking mechanism, so that the timer thread deletes the contained object only if the mutex is unlocked. But this leaves responsablility to the client code to lock and unlock the mutex each time you call a method on the contained object ( ie , in the example,
myobj.Lock();
myobj->iterate();
myobj.UnLock(); )

You could use the Sleep() function that will wait ex: seconds
before continue the code.

Sleep(5000); //Wait 5 seconds /5000 milliseconds

//Destroy/Delete object

That's just the point that an object per se in C++ is a passive entity. It comes into being, lives and dies with the aid of a thread (or process - an active entity) only. Of course. it's possible to set a death timer then... what? It's not an object catches a timer interrupt: it's a thread!

As soon as we understand a passive nature of an object, we can fit a key to the designated problem. Possible solutions:
1. Let the guardian thread maintains a pool of mapping objects (creates, provides access to and kills them). May be, it's the only (main) thread of the application. Remember asynchronous i/o standard logic.
2. Let every such object lives itself with its own thread (process). Remember http requests and (most of) web-server standard logics.

As kux mentioned in both (and others) cases you need (more or less) well-designed access synchronization logics. That's why I said about application architecture issues.

Apropos, Sleep function does not bear a relation to the problem: it suspends the active thread, DNS server (or what else) does nothing. As usually, classic army logics does not work in this case (if you don't know what to do now, go to bed ;) )...

That's just the point that an object per se in C++ is a passive entity. It comes into being, lives and dies with the aid of a thread (or process - an active entity) only. Of course. it's possible to set a death timer then... what? It's not an object catches a timer interrupt: it's a thread!

As soon as we understand a passive nature of an object, we can fit a key to the designated problem. Possible solutions:
1. Let the guardian thread maintains a pool of mapping objects (creates, provides access to and kills them). May be, it's the only (main) thread of the application. Remember asynchronous i/o standard logic.
2. Let every such object lives itself with its own thread (process). Remember http requests and (most of) web-server standard logics.

As kux mentioned in both (and others) cases you need (more or less) well-designed access synchronization logics. That's why I said about application architecture issues.

Apropos, Sleep function does not bear a relation to the problem: it suspends the active thread, DNS server (or what else) does nothing. As usually, classic army logics does not work in this case (if you don't know what to do now, go to bed ;) )...

ok, i know this is an old thread and i'm not suppose to bring it up again, but I find this iteresting.
I posted before a method of providing a wrapper class that deletes an object after X seconds. It worked ok, but it forced the client to write code that explicitly locked and unlocked the mutex before and after each method call so that the object won't get destroyed while a method is called.
Now i found an article from Stroustrup that explains how to write a wraper class that wraps methos calls . This is ok, as with this you can do the lock and unlock inside the wrapper.

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

using namespace std;

//forward
template < class T >
class ObjTimerWrapper;

class Exception {};

template < class T >
class Call_proxy
{
	T* obj_;
	ObjTimerWrapper<T> *twrap_;
public:
	Call_proxy( T* obj, ObjTimerWrapper<T> *twrap ): obj_(obj), twrap_(twrap) {}
	~Call_proxy() { twrap_->UnLock(); }
	T* operator->(){ return obj_; }
};

template < class T>
class ObjTimerWrapper
{
private:
    T* obj_;    

    int seconds_;

    pthread_mutex_t mutex;
    pthread_t timer;
    void DeleteObj()
    {
        pthread_mutex_lock( &mutex );
        delete obj_;
        obj_ = 0;
        pthread_mutex_unlock( &mutex );
    }

    void Lock() { pthread_mutex_lock( &mutex ); }
    void UnLock() { pthread_mutex_unlock( &mutex ); }
    
    friend class Call_proxy<T>;

public:
    ObjTimerWrapper( T* obj, unsigned int seconds):obj_(obj), seconds_(seconds)
    {
        pthread_mutex_init( &mutex, 0 );
        pthread_create(&timer, NULL, ObjTimerWrapper::startTimer, (void*)this );        
    }

    ~ObjTimerWrapper()
    {
        pthread_join( timer, 0 );
        pthread_mutex_destroy(&mutex);
        cout<<"destructor called"<<endl;
    }

    Call_proxy<T> operator->()
    {
        if ( ! obj_ ) throw Exception();
	Lock();
        return Call_proxy<T>( obj_, this );
    }
    T* get()
    {
        if ( ! obj_ ) throw Exception();
        return obj_;
    }
    
    static void* startTimer(void * arg);
    
};

template < class T>
void *ObjTimerWrapper<T>::startTimer(void* arg)
{
    ObjTimerWrapper* p = (ObjTimerWrapper*)arg;
    
    sleep( p->seconds_);    
    
    p->DeleteObj();

    cout<<"timer expired, object destroyed-----------"<<endl;
    return 0;
}

class X
{
public:
    double x;
    void iterate();
    X( float xx ):x(xx){}
};

void X::iterate()
{
    for( int i = 0; i < 1; ++i )
    {
        sleep(5);
    }
    cout<<"rdy"<<endl;
}


int main ( int argc, char* argv[] )
{
    {
        ObjTimerWrapper<X> myobj( new X(0), 3 );
        //myobj.Lock(); //this no longer required
        myobj->iterate();
        //myobj.UnLock(); //this no longer required    

	ObjTimerWrapper<X> mysecobj( new X(0), 9 );
	mysecobj->iterate();

    }
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.