473,756 Members | 6,106 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

a really simple C++ abstraction around pthread_t...

I use the following technique in all of my C++ projects; here is the example
code with error checking omitted for brevity:
_______________ _______________ _______________ _______________ _____
/* Simple Thread Object
_______________ _______________ _______________ _______________ __*/
#include <pthread.h>
extern "C" void* thread_entry(vo id*);

class thread_base {
pthread_t m_tid;
friend void* thread_entry(vo id*);
virtual void on_active() = 0;

public:
virtual ~thread_base() = 0;

void active_run() {
pthread_create( &m_tid, NULL, thread_entry, this);
}

void active_join() {
pthread_join(m_ tid, NULL);
}
};

thread_base::~t hread_base() {}

void* thread_entry(vo id* state) {
reinterpret_cas t<thread_base*> (state)->on_active();
return 0;
}

template<typena me T>
struct active : public T {
active() : T() {
this->active_run() ;
}

~active() {
this->active_join( );
}

template<typena me T_p1>
active(T_p1 p1) : T(p1) {
this->active_run() ;
}

template<typena me T_p1, typename T_p2>
active(T_p1 p1, T_p2 p2) : T(p1, p2) {
this->active_run() ;
}

// [and on and on for more params...]
};


/* Simple Usage Example
_______________ _______________ _______________ _______________ __*/
#include <string>
#include <cstdio>
class worker : public thread_base {
std::string const m_name;

void on_active() {
std::printf("(% p)->worker(%s)::on _thread_entry() \n",
(void*)this, m_name.c_str()) ;
}

public:
worker(std::str ing const& name)
: m_name(name) {
std::printf("(% p)->worker(%s)::my _thread()\n",
(void*)this, m_name.c_str()) ;
}

~worker() {
std::printf("(% p)->worker(%s)::~m y_thread()\n",
(void*)this, m_name.c_str()) ;
}
};
class another_worker : public thread_base {
unsigned const m_id;
std::string const m_name;

void on_active() {
std::printf("(% p)->my_thread(%u/%s)::on_thread_ entry()\n",
(void*)this, m_id, m_name.c_str()) ;
}

public:
another_worker( unsigned const id, std::string const& name)
: m_id(id), m_name(name) {
}
};
int main(void) {
{
active<workerwo rkers[] = {
"Chris",
"John",
"Jane",
"Steve",
"Richard",
"Lisa"
};

active<another_ workerother_wor kers[] = {
active<another_ worker>(21, "Larry"),
active<another_ worker>(87, "Paul"),
active<another_ worker>(43, "Peter"),
active<another_ worker>(12, "Shelly"),
};
}

std::puts("\n\n \n_____________ _____\nhit <ENTERto exit...");
std::fflush(std out);
std::getchar();
return 0;
}
_______________ _______________ _______________ _______________ _____


I personally like this technique better than Boost. I find it more straight
forward and perhaps more object oriented, the RAII nature of the `active'
helper class does not hurt either. Also, I really do think its more
"efficient" than Boost in the way it creates threads because it does not
copy anything...

IMHO, the really nice thing about it would have to be the `active' helper
class. It allows me to run and join any object from the ctor/dtor that
exposes a common interface of (T::active_run/join). Also, it allows me to
pass a variable number of arguments to the object it wraps directly through
its ctor; this is fairly convenient indeed...
Any suggestions on how I can improve this construct?

Oct 30 '08
17 5816
What exactly do you have in mind wrt integrating monitor, when keyword and
active object? How far off the corrected version of my example?

http://groups.google.com/group/comp....9f7980d9323edc
BTW, sorry for posting the broken version:

http://groups.google.com/group/comp....62e9a5d41a6ae6
I jumped the gun!

Oct 31 '08 #11
Given the fixed version I posted here:

http://groups.google.com/group/comp....9f7980d9323edc

one can easily create multiple producers and consumers like this:


int main(void) {
{
bounded_buffer< unsignedb(BOUND );
active<producer p[] = { &b, &b, &b, &b, &b, &b };
active<consumer c[] = { &b, &b, &b, &b, &b, &b };
}

std::puts("\n\n \n_____________ _____\nhit <ENTERto exit...");
std::fflush(std out);
std::getchar();
return 0;
}


I really do like the convenience of the `active' helper template. Anyway,
one caveat wrt the way these specific consumers are coded to act on data,
the number of producers and consumers must be equal.

Oct 31 '08 #12
On Oct 31, 10:14*pm, "Chris M. Thomasson" <n...@spam.inva lidwrote:
What exactly do you have in mind wrt integrating monitor, when keyword and
active object?
I did not meant integrating all the three but it is an interesting
idea too.

I meant that if we have high level wrappers for easy coding of the
monitor construction, it is possible to put together applications
where there are active objects and passive ones for shared data
communication around. One such an example is the producers and
consumers example.
How far off the corrected version of my example?
It is promising. Better than I expected, however, the `broadcast();'
should be also included into the RAII (the `when' object).

I did not think of using the preprocessor for the task but rather some
pure C++ construction. That is why I thought that the RAII object
could not only be a simple `lock_guard' but something like a
`when_guard'. Then one does not have to explicitly place the
`broadcast();' and the `while (! (mp_pred)) this->wait();' can be part
of the constructor of the `when_guard'.

On the other hand, the preprocessor allows to keep the more natural
syntax.

Best Regards,
Szabolcs
Oct 31 '08 #13
[added: comp.lang.c++

here is link to Ulrich Eckhardt's full post because I snipped some of it:

http://groups.google.com/group/comp....190e3b9ac81a69

]

"Ulrich Eckhardt" <do******@knuut .dewrote in message
news:6n******** ****@mid.uni-berlin.de...
Chris M. Thomasson wrote:
[C++ thread baseclass with virtual run() function]

Just one thing technical about the code: your use reinterpret_cas t in a
place that actually calls for a static_cast. A static_cast is the right
tool to undo the implicit conversion from T* to void*.
>I personally like this technique better than Boost. I find it more
straight forward and perhaps more object oriented, the RAII nature of the
`active' helper class does not hurt either. Also, I really do think its
more "efficient" than Boost in the way it creates threads because it does
not copy anything...

There are two things that strike me here:
1. You mention "object oriented" as if that was a goal, but it isn't.
Rather, it is a means to achieve something, and the question is always
valid whether its use is justified. Java's decision to force an OO design
on you and then inviting other paradigms back in through the backdoor is
the prime example for misunderstood OO. Wrapping a thread into a class the
way you do it is another IMHO, ill explain below.
2. What exactly is the problem with the copying? I mean you're starting a
thread, which isn't actually a cheap operation either. Further, if you
want, you can optimise that by using transfer of ownership (auto_ptr) or
shared ownership (shared_ptr) in case you need. Boost doesn't make it
necessary to copy anything either (except under the hood it does some
dynamic allocation), but also allows you to chose if you want. However,
copying and thus avoiding shared data is the safer default, because any
shared data access requires care.
[...]

If find it unfortunate to be forced to use an smart pointers and dynamically
created objects just to be able to pass common shared data to a thread. I am
still not convinced that treating a thread as an object is a bad thing...
For instance...
How would I be able to create the following fully compliable program (please
refer to the section of code under the "Simple Example" heading, the rest is
simple impl detail for pthread abstraction) using Boost threads. The easy
way to find the example program is to go to the end of the entire program,
and start moving up until you hit the "Simple Example" comment... Here it
is:
_______________ _______________ _______________ _______________ _________

/* Simple Thread Object
_______________ _______________ _______________ _______________ __*/
#include <pthread.h>
extern "C" void* thread_entry(vo id*);

class thread_base {
pthread_t m_tid;
friend void* thread_entry(vo id*);
virtual void on_active() = 0;

public:
virtual ~thread_base() = 0;

void active_run() {
pthread_create( &m_tid, NULL, thread_entry, this);
}

void active_join() {
pthread_join(m_ tid, NULL);
}
};

thread_base::~t hread_base() {}

void* thread_entry(vo id* state) {
reinterpret_cas t<thread_base*> (state)->on_active();
return 0;
}
template<typena me T>
struct active : public T {
struct guard {
T& m_object;

guard(T& object) : m_object(object ) {
m_object.active _run();
}

~guard() {
m_object.active _join();
}
};

active() : T() {
this->active_run() ;
}

~active() {
this->active_join( );
}

template<typena me T_p1>
active(T_p1 p1) : T(p1) {
this->active_run() ;
}

template<typena me T_p1, typename T_p2>
active(T_p1 p1, T_p2 p2) : T(p1, p2) {
this->active_run() ;
}

template<typena me T_p1, typename T_p2, typename T_p3>
active(T_p1 p1, T_p2 p2, T_p3 p3) : T(p1, p2, p3) {
this->active_run() ;
}

// [and on and on for more params...]
};


/* Simple Monitor
_______________ _______________ _______________ _______________ __*/
class monitor {
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;

public:
monitor() {
pthread_mutex_i nit(&m_mutex, NULL);
pthread_cond_in it(&m_cond, NULL);
}

~monitor() {
pthread_cond_de stroy(&m_cond);
pthread_mutex_d estroy(&m_mutex );
}

struct lock_guard {
monitor& m_monitor;

lock_guard(moni tor& monitor_) : m_monitor(monit or_) {
m_monitor.lock( );
}

~lock_guard() {
m_monitor.unloc k();
}
};

struct signal_guard {
monitor& m_monitor;
bool const m_broadcast;

signal_guard(mo nitor& monitor_, bool broadcast = true)
: m_monitor(monit or_), m_broadcast(bro adcast) {

}

~signal_guard() {
if (m_broadcast) {
m_monitor.broad cast();
} else {
m_monitor.signa l();
}
}
};

void lock() {
pthread_mutex_l ock(&m_mutex);
}

void unlock() {
pthread_mutex_u nlock(&m_mutex) ;
}

void wait() {
pthread_cond_wa it(&m_cond, &m_mutex);
}

void signal() {
pthread_cond_si gnal(&m_cond);
}

void broadcast() {
pthread_cond_br oadcast(&m_cond );
}
};
#define when_xx(mp_pred , mp_line) \
monitor::lock_g uard lock_guard_##mp _line(*this); \
monitor::signal _guard signal_guard_## mp_line(*this); \
while (! (mp_pred)) this->wait();

#define when_x(mp_pred, mp_line) when_xx(mp_pred , mp_line)
#define when(mp_pred) when_x(mp_pred, __LINE__)



/* Simple Example
_______________ _______________ _______________ _______________ __*/
#include <string>
#include <deque>
#include <cstdio>
template<typena me T>
struct bounded_buffer : monitor {
unsigned const m_max;
std::deque<Tm_b uffer;

public:
bounded_buffer( unsigned const max_) : m_max(max_) {}

void push(T const& obj) {
when (m_buffer.size( ) < m_max) {
m_buffer.push_b ack(obj);
}
}

T pop() {
when (! m_buffer.empty( )) {
T obj = m_buffer.front( );
m_buffer.pop_fr ont();
return obj;
}
}
};
struct person : thread_base {
typedef bounded_buffer< std::stringqueu e;
std::string const m_name;
queue& m_response;

public:
queue m_request;

void on_active() {
m_response.push (m_name + " is ready to receive some questions!");
for (unsigned i = 0 ;; ++i) {
std::string msg(m_request.p op());
if (msg == "QUIT") { break; }
std::printf("(Q )->%s: %s\n", m_name.c_str(), msg.c_str());
switch (i) {
case 0:
msg = "(A)->" + m_name + ": Well, I am okay";
break;

case 1:
msg = "(A)->" + m_name + ": I already told you!";
break;

default:
msg = "(A)->" + m_name + ": I am PISSED OFF NOW!";
}
m_response.push (msg);
}
std::printf("%s was asked to quit...\n", m_name.c_str()) ;
m_response.push (m_name + " is FINISHED");
}

person(std::str ing const& name, queue* q, unsigned const bound)
: m_name(name), m_response(*q), m_request(bound ) {}
};
#define BOUND 10
int main(void) {
{
person::queue response(BOUND) ;

active<personch ris("Chris", &response, BOUND);
active<personam y("Amy", &response, BOUND);

std::printf("%s \n", response.pop(). c_str());
std::printf("%s \n\n", response.pop(). c_str());

chris.m_request .push("How are you doing?");
amy.m_request.p ush("How are you feeling?");
std::printf("%s \n", response.pop(). c_str());
std::printf("%s \n\n", response.pop(). c_str());

chris.m_request .push("Do you really feel that way?");
amy.m_request.p ush("Are you sure?");
std::printf("%s \n", response.pop(). c_str());
std::printf("%s \n\n", response.pop(). c_str());

chris.m_request .push("Why do you feel that way?");
amy.m_request.p ush("Can you share more of you feelings?");
std::printf("%s \n", response.pop(). c_str());
std::printf("%s \n\n", response.pop(). c_str());

chris.m_request .push("QUIT");
amy.m_request.p ush("QUIT");

std::printf("%s \n", response.pop(). c_str());
std::printf("%s \n", response.pop(). c_str());
}

std::puts("\n\n \n_____________ _____\nhit <ENTERto exit...");
std::fflush(std out);
std::getchar();
return 0;
}

_______________ _______________ _______________ _______________ _________


Please correct me if I am wrong, but Boost would force me to dynamically
create the `person::queue request' object in main right? AFAICT, this
example shows why is can be a good idea to treat a thread as an object. In
this case, a person object is a thread. Anyway, as of now, I am not entirely
convinced that Boost has a far superior method of creating threads...


Anyway, I really do need to think about the rest of your post; you raise
several interesting issues indeed.

Nov 2 '08 #14

"Chris M. Thomasson" <no@spam.invali dwrote in message
news:XR******** *********@newsf e01.iad...
[...]
"Ulrich Eckhardt" <do******@knuut .dewrote in message
news:6n******** ****@mid.uni-berlin.de...
>Chris M. Thomasson wrote:
[...]>
If find it unfortunate to be forced to use an smart pointers and
dynamically created objects just to be able to pass common shared data to
a thread. I am still not convinced that treating a thread as an object is
a bad thing... For instance...
How would I be able to create the following fully compliable program
(please refer to the section of code under the "Simple Example" heading,
the rest is simple impl detail for pthread abstraction) using Boost
threads. The easy way to find the example program is to go to the end of
the entire program, and start moving up until you hit the "Simple Example"
comment... Here it is:
_______________ _______________ _______________ _______________ _________
[...]
_______________ _______________ _______________ _______________ _________


Please correct me if I am wrong, but Boost would force me to dynamically
create the `person::queue request' object in main right? AFAICT, this
example shows why is can be a good idea to treat a thread as an object. In
this case, a person object is a thread. Anyway, as of now, I am not
entirely convinced that Boost has a far superior method of creating
threads...
[...]

I should have made the characters `Chris' and `Amy' completely separate
objects deriving from a `person' base-class . That way, their personalities
and therefore their responses would not be identical. Treating threads as
objects works very well for me perosnally...

Nov 2 '08 #15
Responding late, it was a rough week...

Chris M. Thomasson wrote:
"Ulrich Eckhardt" <do******@knuut .dewrote in message
news:6n******** ****@mid.uni-berlin.de...
>Chris M. Thomasson wrote:
[C++ thread baseclass with virtual run() function]
>>I personally like this technique better than Boost. I find it more
straight forward and perhaps more object oriented, the RAII nature of
the `active' helper class does not hurt either. Also, I really do think
its more "efficient" than Boost in the way it creates threads because it
does not copy anything...

There are two things that strike me here:
1. You mention "object oriented" as if that was a goal, but it isn't.
Rather, it is a means to achieve something, and the question is always
valid whether its use is justified. Java's decision to force an OO design
on you and then inviting other paradigms back in through the backdoor is
the prime example for misunderstood OO. Wrapping a thread into a class
the way you do it is another IMHO, ill explain below.
2. What exactly is the problem with the copying? I mean you're starting a
thread, which isn't actually a cheap operation either. Further, if you
want, you can optimise that by using transfer of ownership (auto_ptr) or
shared ownership (shared_ptr) in case you need. Boost doesn't make it
necessary to copy anything either (except under the hood it does some
dynamic allocation), but also allows you to chose if you want. However,
copying and thus avoiding shared data is the safer default, because any
shared data access requires care.

[...]

If find it unfortunate to be forced to use an smart pointers and
dynamically created objects just to be able to pass common shared data to
a thread. I am still not convinced that treating a thread as an object is
a bad thing... For instance...
How would I be able to create the following fully compliable program
(please refer to the section of code under the "Simple Example" heading,
the rest is simple impl detail for pthread abstraction) using Boost
threads. The easy way to find the example program is to go to the end of
the entire program, and start moving up until you hit the "Simple Example"
comment...
If I get your code right, this program is creating two threads, each of
which models a person's behaviour. The main thread then asks them questions
which are stored in a queue to be handled asynchronously and prints the
answers which are received from another queue. Is that right?

Now, how would I rather design this? Firstly, I would define the behaviour
of the persons in a class. This class would be completely ignorant of any
threading going on in the background and only model the behaviour.

Then, I would create a type that combines a queue with a condition and a
mutex. This could then be used to communicate between threads in a safe
way. This would be pretty much the same as your version, both
pthread_cond_t and pthread_mutex_t translate easily to boost::mutex and
boost::conditio n.
Now, things get a bit more complicated, because first some questions need to
be answered. The first one is what the code should do in case of failures.
What happens if one person object fails to answer a question? What if
answering takes too long? What if the thread where the answers are
generated is terminated due to some error? What if the invoking thread
fails to queue a request, e.g. due to running out of memory?

The second question to answer is what kind of communication you are actually
modelling here. In the example, it seems as if you were making a request
and then receiving the response to that request, but that isn't actually
completely true. Rather, the code is sending a message and receiving a
message, but there is no correlation between the sent and received message.
If this correlation is required, I would actually return a cookie when I
make a request and retrieve the answer via that cookie.

In any case, you can write an equivalent program using Boost.Thread. If you
want, you can wrap stuff into a class, e.g. like this:

struct active_person
{
explicit active_person(q ueue& out_):
out(out_),
th( bind( &handle_request s, this))
{}
~active_person( )
{ th.join(); }
void push_question( std::string const& str)
{ in.push(str); }
std::string pop_answer()
{ return out.pop(); }
private:
void handle_requests ()
{
while(true)
{
std::string question = in.pop();
if(question=="Q UIT")
return;
out.push(p.ask( question));
}
}
queue in;
queue& out;
person p;
// note: this one must come last, because its initialisation
// starts a thread using this object.
boost::thread th;
};

You could also write a simple function:

void async_quiz( person& p, queue& questions, queue& answers)
{
while(true)
{
std::string question = questions.pop() ;
if(question=="Q UIT")
return;
answers.push(p. ask(question));
}
}

queue questions, answers;
person amy("amy");
thread th(bind( &async_quiz, ref(amy),
ref(questions), ref(answers)));
.... // ask questions
th.join();

Note the use of ref() to avoid the default copying of the argument. Using
pointers would work, too, but I find it ugly.

In any case, this is probably not something I would write that way. The
point is that I can not force a thread to shut down or handle a request. I
can ask it to and maybe wait for it (possibly infinitely), but I can not
force it. So, if there is any chance for failure, both on the grounds of
request handling or the request handling mechanism in general, this
approach becomes unusable. Therefore, I rather prepare for the case that a
thread becomes unresponsive by allowing it to run detached from the local
stack.

Writing about that, there is one thing that came somehow as a revelation to
me, and that was the Erlang programming language. It has concurrency built
in and its threads (called processes) communicate using messages. Using a
similar approach in C++ allows writing very clean programs that don't
suffer lock contention. In any case, I suggest taking a look at Erlang just
for the paradigms, I found some really good ideas to steal from there. ;)

#define when_xx(mp_pred , mp_line) \
monitor::lock_g uard lock_guard_##mp _line(*this); \
monitor::signal _guard signal_guard_## mp_line(*this); \
while (! (mp_pred)) this->wait();

#define when_x(mp_pred, mp_line) when_xx(mp_pred , mp_line)
#define when(mp_pred) when_x(mp_pred, __LINE__)
Just one note on this one: When I read your example, I stumbled over the use
of a 'when' keyword where I would expect an 'if'. I find this here really
bad C++ for several reasons:
1. Macros should be UPPERCASE_ONLY. That way, people see that it's a macro
and they know that it may or may not behave like a function. It simply
avoids surprises.
2. It is used in a way that breaks its integration into the control flow
syntax. Just imagine that I would use it in the context of an 'if'
expression:

if(something)
when(some_condi tion)
do_something_el se();

I'd rather write it like this:

if(something) {
LOCK_AND_WAIT_C ONDITION(some_c ondition);
do_something_el se();
}

Firstly, you see that these are separate statements and this then
automatically leads to you adding the necessary curly braces.
Please correct me if I am wrong, but Boost would force me to dynamically
create the `person::queue request' object in main right?
No. The argument when starting a thread is something that can be called,
like a function or functor, that's all. This thing is then copied before it
is used by the newly started thread. Typically, this thing is a function
bound to its context arguments using Boost.Bind or Lambda. If you want, you
can make this a simple structure containing a few pointers or references,
i.e. something dead easy to copy.

cheers

Uli

Nov 6 '08 #16
On Nov 6, 11:24*pm, Ulrich Eckhardt <dooms...@knuut .dewrote:
Responding late, it was a rough week...

Chris M. Thomasson wrote:
"Ulrich Eckhardt" <dooms...@knuut .dewrote in message
news:6n******** ****@mid.uni-berlin.de...
Chris M. Thomasson wrote:
[...]
#define when_xx(mp_pred , mp_line) \
* monitor::lock_g uard lock_guard_##mp _line(*this); \
* monitor::signal _guard signal_guard_## mp_line(*this); \
* while (! (mp_pred)) this->wait();
#define when_x(mp_pred, mp_line) when_xx(mp_pred , mp_line)
#define when(mp_pred) when_x(mp_pred, __LINE__)

Just one note on this one: When I read your example, I stumbled over the use
of a 'when' keyword where I would expect an 'if'.
The `when' is basically different from the `if'.

Since I have come up with this construction, I might give you an
answer. The `when' is not a genuine keyword since it is still C++ code
and the `when' is not a C++ keyword. However, here we are
experimenting whether a programming style could be applied in a C++
program that mimics the original Conditional Critical Region
programming proposal where the `when' is a keyword.

The `if' is a sequential control statement whereas the `when' is not
one. The semantics of the `if' and the `when' differs in that the `if'
fails when the condition does not hold at the time it is evaluated and
the statement takes the `else' branch if it is given. The `when'
keyword, on the other hand, delays the thread until the condition is
not true. In other words, the `when' specifies a guard.
I find this here really
bad C++ for several reasons:
1. Macros should be UPPERCASE_ONLY. That way, people see that it's a macro
and they know that it may or may not behave like a function. It simply
avoids surprises.
It is not necessarily meant to be a macro, the macro is just one
possible implementation of the construction.
2. It is used in a way that breaks its integration into the control flow
syntax. Just imagine that I would use it in the context of an 'if'
expression:

* if(something)
* * when(some_condi tion)
* * * do_something_el se();

I'd rather write it like this:

* if(something) {
* * LOCK_AND_WAIT_C ONDITION(some_c ondition);
* * do_something_el se();
* }

Firstly, you see that these are separate statements and this then
automatically leads to you adding the necessary curly braces.
Please check out the post where the `when' construction is introduced
into this discussion thread:

http://groups.google.com/group/comp....476c1c7d91c008

If you have an idea how to solve the original problem I described,
your solution is welcome.

Best Regards,
Szabolcs
Nov 7 '08 #17

"Ulrich Eckhardt" <do******@knuut .dewrote in message
news:6n******** ****@mid.uni-berlin.de...
Responding late, it was a rough week...
[...]
In any case, you can write an equivalent program using Boost.Thread. If
you
want, you can wrap stuff into a class, e.g. like this:

struct active_person
{
explicit active_person(q ueue& out_):
out(out_),
th( bind( &handle_request s, this))
{}
~active_person( )
{ th.join(); }
void push_question( std::string const& str)
{ in.push(str); }
std::string pop_answer()
{ return out.pop(); }
private:
void handle_requests ()
{
while(true)
{
std::string question = in.pop();
if(question=="Q UIT")
return;
out.push(p.ask( question));
}
out.push("QUIT" );
}
queue in;
queue& out;
person p;
// note: this one must come last, because its initialisation
// starts a thread using this object.
boost::thread th;
};
[...]
I would create the active template using Boost like:

// quick sketch - may have typo
_______________ _______________ _______________ _______________ ___________
template<typena me T>
class active : public T {
boost::thread m_active_handle ;

public:
active() : T(), m_active_handle (bind(&on_activ e, (T*)this)) {}

~active() { m_active_handle .join(); }

template<typena me P1>
active(P1 p1) : T(p1),
m_active_handle (bind(&on_activ e, (T*)this)) {}

template<typena me P1, typename P2>
active() : T(P1, P2),
m_active_handle (bind(&on_activ e, (T*)this)) {}

// [on and on for more params...]
};
_______________ _______________ _______________ _______________ ___________


Then I could use it like:
struct person {
void on_active() {
// [...]
}
};
int main() {
active<personp[10];
return 0;
}

I personally like this construction; I think its "cleaner" than using the
Boost interface "directly".

Nov 9 '08 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
1227
by: Dave Benjamin | last post by:
The recent conversation on prototype-based OOP and the Prothon project has been interesting. I've been playing around with the idea for awhile now, actually, since I do a lot of programming in JavaScript/ActionScript. I feel like people are focusing too much on the "prototype chain", which to me is mainly an attempt at reintroducing inheritance. I almost never use inheritance anymore, preferring delegation instead in most cases. What I...
26
1811
by: DeMarcus | last post by:
Let's say we're gonna make a system library and have a class with two prerequisites. * It will be used _a_lot_, and therefore need to be really efficient. * It can have two different implementations. (e.g. Unix/Windows) I feel stuck. The only solution I've seen so far is using the design pattern 'abstract factory' that gives me a pointer to a pure virtual interface (which can have whatever implementation). But that forces me to make a...
10
2377
by: serge calderara | last post by:
Dear all, I need to build a web application which will contains articles (long or short) I was wondering on what is the correct way to retrive those article on web page. In orther words, when there is such information to be displayed are they coming from imported files, database ? Where and how this type of information is stored ? What is the way to retrieve such information in order to display it in page ?
1
2333
by: DartmanX | last post by:
I'm looking for any comparisons of PHP Database Abstraction Layers out there, with an eye towards speed/efficiency. I'm still using PEAR::DB, which obviously leaves something to be desired. I'm at a point now where I can look at switching to a better system. Jason
25
2562
by: Colin McKinnon | last post by:
Hi all, There's lots of DB abstraction layers out there, but a quick look around them hasn't turned up anything which seems to met my requirements. Before I go off and write one I thought I'd ask here if anyone knows of such a beast... I want some code where I present an array of data, and the corresponding primary key and let the code work out whether to INSERT or UPDATE it, I also want to be able to present the data from a QBF or...
3
5095
by: S. Lorétan | last post by:
Hi guys, I'm coding an application connected to a database. I have some clients that use this program with 2 or 3 computers, and I use MsSQL Express for them. But if the client needs more computers to be connected to the database, I have to use a standard MsSQL. No problem with that, but I want to be able to switch from a database provider to another in an easy way. I know that this way to do is called "Data(base) abstraction layer",...
1
1676
by: rickycornell | last post by:
Greetings All, On past projects in PHP4 I had always just written my own libraries to deal with database interaction. Somehow I was operating in the dark that there were all these database abstraction things available that made my work on the libraries I made from scratch a waste of time. So now I've started researching all these things that are available, and I have to say I am a little confused. It's a matter of understanding the...
3
1906
by: TamusJRoyce | last post by:
Hello. This is my first thread here. My problem has probably been came across by a lot of people, but tutorials and things I've seen don't address it (usually too basic). My problem is that I would like to use Abstraction for a "plug-in" like interface to classes. class ThreadHandle { /* stuff here not yet dealing with threads */
6
9370
by: pythoNewbie | last post by:
Dear experts, I am trying to understand a simple semaphore program written in C, and trying to insert some printf statements in the code , but there is no output at all. #include<stdio.h> #include<phtread.h> #include<sys/ipc.h> #include<sys/sem.h>
0
9271
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9868
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9836
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8709
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7242
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6533
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5301
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3352
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2664
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.