The name is "Common C++" but it's not very C++ish, is it?
The source code is #ifdef hell. It's not easily readable, and it avoids a lot of established object-oriented patterns and methodologies which would make the code significantly more modular and flexible, especially for porting work.
For example, the use of pure virtual classes to represent interfaces: A thread object is an instance of a class that implements IThread. For each porting target, provide a factory that implements IThreadFactory, which produces thread instances specific to the OS. Win32ThreadFactory produces IThread impls that uses the Win32 threading API; PthThreadFactory uses GNU Pth; GreenThreadFactory uses some userland thread library; and so forth. See where I'm getting at?
The implementation is not relevant to the *user* of the API. All I -- as the user -- want is a set of implementation-neutral header files defining the *interface* to the API. Too many libraries make the mistake of mixing interface and implementation.
Thoughts? I would be glad to lend a hand.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes, header are not so good... but if you want a fast API you must use inline, so we use define...
A class factory?
You can't use inheriting with class factory... you must use decorator... not so good.
Yes, there are many bad code, like friend instead of members.
I have merged win32 and posix very shortly, so header is not so good, I'm cleanup them...
Also I wanted binary compatibility and members hiding for dll/so, but dyfet prefer speed and name change... went merging is finished I want to find a method for selecting hiding/not hiding during compile
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm not talking about inheritance of class factories. You would have something like this:
class IThreadFactory
{
public:
virtual IThread* newThread() = 0;
};
That's all a user needs to see. The rest is an implementation detail.
Cleaning up sounds good. Overall it sounds like the project is in a flux. I have looked at ACE, which is a much more mature project (even if the design is just as much "C plus classes" as Common C++), but it's much too heavy for my needs. But it sounds like I will have to do with hacks until something better comes along.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I see what you mean, and using decorators is one way to improve the current design.
However, I have to stress the importance of abstracting the *interface*. You should have classes implementing (inheriting from, since in C++ an interface is purely an idiomatic construct) the appropriate interface.
By using decorators that themselves find the object to decorate, then you are merely munging a factory into the decorator instance itself. Ie., Thread would have code such as:
so you're mostly shifting this responsibility into your primitives, as opposed to central factories.
Even with such decorators, you would benefit from defining interfaces -- pure virtual classes -- for all of your classes. It also means the public delegate and the your private implementation share the same interface.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The name is "Common C++" but it's not very C++ish, is it?
The source code is #ifdef hell. It's not easily readable, and it avoids a lot of established object-oriented patterns and methodologies which would make the code significantly more modular and flexible, especially for porting work.
For example, the use of pure virtual classes to represent interfaces: A thread object is an instance of a class that implements IThread. For each porting target, provide a factory that implements IThreadFactory, which produces thread instances specific to the OS. Win32ThreadFactory produces IThread impls that uses the Win32 threading API; PthThreadFactory uses GNU Pth; GreenThreadFactory uses some userland thread library; and so forth. See where I'm getting at?
The implementation is not relevant to the *user* of the API. All I -- as the user -- want is a set of implementation-neutral header files defining the *interface* to the API. Too many libraries make the mistake of mixing interface and implementation.
Thoughts? I would be glad to lend a hand.
Yes, header are not so good... but if you want a fast API you must use inline, so we use define...
A class factory?
You can't use inheriting with class factory... you must use decorator... not so good.
Yes, there are many bad code, like friend instead of members.
I have merged win32 and posix very shortly, so header is not so good, I'm cleanup them...
Also I wanted binary compatibility and members hiding for dll/so, but dyfet prefer speed and name change... went merging is finished I want to find a method for selecting hiding/not hiding during compile
I'm not talking about inheritance of class factories. You would have something like this:
class IThreadFactory
{
public:
virtual IThread* newThread() = 0;
};
That's all a user needs to see. The rest is an implementation detail.
Cleaning up sounds good. Overall it sounds like the project is in a flux. I have looked at ACE, which is a much more mature project (even if the design is just as much "C plus classes" as Common C++), but it's much too heavy for my needs. But it sounds like I will have to do with hacks until something better comes along.
The inheritance problem is this, IThread should be defined as:
class IThread
{
public:
...
void Run()=0;
...
};
so, you must derive from IThread to create a thread... how inheriting using a factory like your one?
Best use hidden implementation like:
class Thread
{
private:
class PrivateThread;
PrivateThread* priv;
public:
...
void Run()=0;
...
};
So you can inheritate from Thread and separate implementation...
I see what you mean, and using decorators is one way to improve the current design.
However, I have to stress the importance of abstracting the *interface*. You should have classes implementing (inheriting from, since in C++ an interface is purely an idiomatic construct) the appropriate interface.
By using decorators that themselves find the object to decorate, then you are merely munging a factory into the decorator instance itself. Ie., Thread would have code such as:
Thread::Thread()
{
#ifdef __PTHREAD__
priv = new PthThread();
#else
...
}
so you're mostly shifting this responsibility into your primitives, as opposed to central factories.
Even with such decorators, you would benefit from defining interfaces -- pure virtual classes -- for all of your classes. It also means the public delegate and the your private implementation share the same interface.
Modern (but young) C++ threads library:
http://www.boost.org/libs/thread/doc/index.html