473,403 Members | 2,323 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,403 software developers and data experts.

Factory method -- best practices for portability

Hi,

I'm a long-time C programmer, I've started making the transition to "real
C++" recently. I am puzzled about how to write a factory method. Any
suggestions, pointers or references to documentation would be appreciated.

Here is some background information about what I'm doing: I have written a
large body of code that makes extensive use of mutexes. Most of my code is
portable, except for the mutexes, which are platform specific. I've
abstracted the notion of mutex with an abstract class "mutex", with pure
virtual functions get() and release() to obtain and release the mutex,
respectively. The large body of code uses pointers to these mutexes.

I am deriving "implementation classes" from mutex, for example win32Mutex,
linuxMutex, and posixMutex, on a per-platform basis and implementing get()
and release() accordingly.

Everything seems to be working OK with my simple tests, but I want to use a
"factory method" to cleanly produce (pointers to) mutexes. I can't grok how
to do this at a high-level, and I can't quite "seal off" the
platform-specific code from the large body of platform-independent code.

The idea is that I want to minimize platform-specific things in the large
body of code by calling a factory method when a mutex is needed, as opposed
to calling the (platform specific) constructors in the implementation
classes directly.

Should I:
1) Try to make the factory method a static member function of class mutex?
2) Create another class mutexMaker with member function makeNewMutex(), and
derive classes like win32MutexMaker and linuxMutexMaker from it?
3) Write a non-member function?
4) Use #IFDEF and #INCLUDE and #3 above?
5) Something else that I haven't thought of?

Thanks in advance for any insight.

ed
Jul 22 '05 #1
8 2053
"Ed Fair" <ed*****@mindspring.com> wrote:
I am deriving "implementation classes" from mutex, for example win32Mutex,
linuxMutex, and posixMutex, on a per-platform basis and implementing get()
and release() accordingly.

Everything seems to be working OK with my simple tests, but I want to use a "factory method" to cleanly produce (pointers to) mutexes. I can't grok how to do this at a high-level, and I can't quite "seal off" the
platform-specific code from the large body of platform-independent code. .... Should I:
1) Try to make the factory method a static member function of class mutex?
2) Create another class mutexMaker with member function makeNewMutex(), and derive classes like win32MutexMaker and linuxMutexMaker from it?
3) Write a non-member function?
4) Use #IFDEF and #INCLUDE and #3 above?
5) Something else that I haven't thought of?


Here are some appropriate "design patterns" for this problem:

Abstract Factory (#2 above) -
http://home.earthlink.net/~huston2/dp/factory.html

- particularly used for "families" of class objects, eg. win32Mutex,
win32Socket, linuxMutex, linuxSocket ...

Factory Method - http://home.earthlink.net/~huston2/d...oryMethod.html

- add a virtual newMutex() function to class Mutex, and derive win32Mutex,
linuxMutex etc. from Mutex.

Prototype - http://home.earthlink.net/~huston2/dp/prototype.html

- copy a prototypical example of a mutex (which is created at the beginning
of the program) whenever a new one is needed.
David F


Jul 22 '05 #2
"Ed Fair" <ed*****@mindspring.com> wrote:
I'm a long-time C programmer, I've started making the transition to "real
C++" recently. I am puzzled about how to write a factory method. Any
suggestions, pointers or references to documentation would be appreciated.

Here is some background information about what I'm doing: I have written a
large body of code that makes extensive use of mutexes. Most of my code is
portable, except for the mutexes, which are platform specific. I've
abstracted the notion of mutex with an abstract class "mutex", with pure
virtual functions get() and release() to obtain and release the mutex,
respectively. The large body of code uses pointers to these mutexes.

I am deriving "implementation classes" from mutex, for example win32Mutex,
linuxMutex, and posixMutex, on a per-platform basis and implementing get()
and release() accordingly.

Everything seems to be working OK with my simple tests, but I want to use a
"factory method" to cleanly produce (pointers to) mutexes. I can't grok how
to do this at a high-level, and I can't quite "seal off" the
platform-specific code from the large body of platform-independent code.

The idea is that I want to minimize platform-specific things in the large
body of code by calling a factory method when a mutex is needed, as opposed
to calling the (platform specific) constructors in the implementation
classes directly.

Should I:
1) Try to make the factory method a static member function of class mutex?
2) Create another class mutexMaker with member function makeNewMutex(), and
derive classes like win32MutexMaker and linuxMutexMaker from it?
3) Write a non-member function?
4) Use #IFDEF and #INCLUDE and #3 above?
5) Something else that I haven't thought of?


Your trying too hard Ed. :-) Factory methods are good for runtime
polymorphism, but you don't have any of that in this case. The linux
program will always use linux mutexes for example. You simply need to
create H and CPP files for each mutex type, but give them all the same
interface and class name, then link in the one you want for the version
you are compiling.
Jul 22 '05 #3
Thanks, David, these made for good reading.

ed

"David Fisher" <no****@nospam.nospam.nospam> wrote in message
news:Pl******************@nasal.pacific.net.au...
"Ed Fair" <ed*****@mindspring.com> wrote:
I am deriving "implementation classes" from mutex, for example win32Mutex, linuxMutex, and posixMutex, on a per-platform basis and implementing get() and release() accordingly.

Everything seems to be working OK with my simple tests, but I want to use
a
"factory method" to cleanly produce (pointers to) mutexes. I can't grok how
to do this at a high-level, and I can't quite "seal off" the
platform-specific code from the large body of platform-independent code.

...
Should I:
1) Try to make the factory method a static member function of class

mutex? 2) Create another class mutexMaker with member function makeNewMutex(),

and
derive classes like win32MutexMaker and linuxMutexMaker from it?
3) Write a non-member function?
4) Use #IFDEF and #INCLUDE and #3 above?
5) Something else that I haven't thought of?


Here are some appropriate "design patterns" for this problem:

Abstract Factory (#2 above) -
http://home.earthlink.net/~huston2/dp/factory.html

- particularly used for "families" of class objects, eg. win32Mutex,
win32Socket, linuxMutex, linuxSocket ...

Factory Method - http://home.earthlink.net/~huston2/d...oryMethod.html

- add a virtual newMutex() function to class Mutex, and derive win32Mutex,
linuxMutex etc. from Mutex.

Prototype - http://home.earthlink.net/~huston2/dp/prototype.html

- copy a prototypical example of a mutex (which is created at the

beginning of the program) whenever a new one is needed.
David F

Jul 22 '05 #4
Thanks, Daniel.

ed

"Daniel T." <po********@eathlink.net> wrote in message
news:po******************************@news06.east. earthlink.net...
"Ed Fair" <ed*****@mindspring.com> wrote:
I'm a long-time C programmer, I've started making the transition to "real C++" recently. I am puzzled about how to write a factory method. Any
suggestions, pointers or references to documentation would be appreciated.
Here is some background information about what I'm doing: I have written a large body of code that makes extensive use of mutexes. Most of my code is portable, except for the mutexes, which are platform specific. I've
abstracted the notion of mutex with an abstract class "mutex", with pure
virtual functions get() and release() to obtain and release the mutex,
respectively. The large body of code uses pointers to these mutexes.

I am deriving "implementation classes" from mutex, for example win32Mutex, linuxMutex, and posixMutex, on a per-platform basis and implementing get() and release() accordingly.

Everything seems to be working OK with my simple tests, but I want to use a "factory method" to cleanly produce (pointers to) mutexes. I can't grok how to do this at a high-level, and I can't quite "seal off" the
platform-specific code from the large body of platform-independent code.

The idea is that I want to minimize platform-specific things in the large body of code by calling a factory method when a mutex is needed, as opposed to calling the (platform specific) constructors in the implementation
classes directly.

Should I:
1) Try to make the factory method a static member function of class mutex? 2) Create another class mutexMaker with member function makeNewMutex(), and derive classes like win32MutexMaker and linuxMutexMaker from it?
3) Write a non-member function?
4) Use #IFDEF and #INCLUDE and #3 above?
5) Something else that I haven't thought of?


Your trying too hard Ed. :-) Factory methods are good for runtime
polymorphism, but you don't have any of that in this case. The linux
program will always use linux mutexes for example. You simply need to
create H and CPP files for each mutex type, but give them all the same
interface and class name, then link in the one you want for the version
you are compiling.

Jul 22 '05 #5

"Ed Fair" <ed*****@mindspring.com> wrote in message
news:vO****************@newsread1.news.atl.earthli nk.net...
Hi,

I'm a long-time C programmer, I've started making the transition to "real
C++" recently. I am puzzled about how to write a factory method. Any
suggestions, pointers or references to documentation would be appreciated.

Here is some background information about what I'm doing: I have written a large body of code that makes extensive use of mutexes. Most of my code is portable, except for the mutexes, which are platform specific. I've
abstracted the notion of mutex with an abstract class "mutex", with pure
virtual functions get() and release() to obtain and release the mutex,
respectively. The large body of code uses pointers to these mutexes.


This will significantly slow your code compared to native mutex calls which
are often just macros with
no function call at all if there is no contention.

One responder suggested just linking to different versions which is fine but
still not very efficient.

To get maximum speed the answer is templates
- parameterize everything with a class required to contain all the types and
methods that you need. Default this parameter to ThreadUtil or some such.
- Have a Thread.h header that conditionally includes the appropriate system
header, your platform specific thread class header and which typedefs the
platform specfic classes to ThreadUtil
- Make all the methods of your classes inline

e.g.

PosixThreadUtil.h

#include <pthread.h>
struct PosixThreadUtil
{
struct Mutex
{
pthread_mutex_t m_mutex;
void lock() { pthread_mutex_lock(&m_mutex); }
//etc
};
// threads, condvars etc
};

ThreadUtil.h

#ifdef POSIX_SOURCE
#include "PosixThreadUtil.h"
typedef PosixThreadUtil ThreadUtil;
#elif defined(WIN32)
#include "WindowsThreadUtil.h"
typedef WindowsThreadUtil ThreadUtil;
#else
#error no thread class available
#endif

stuff.cpp

#include "ThreadUtil.h"

template <class THREAD=ThreadUtil>
void unrealistic()
{
typename ThreadUtill::Mutex mutex;
mutex.lock(); // should be inlined to pthread_mutexlock for POSIX
}

This mechanism works and is efficient but be warned - different systems
model threads and their control very differently - mutex/critical section is
easy but there is apparently no simple equivalent to pthread cond in
Windows.
There is a book (sorry - I can't remember the title) that spends several
hundred pages developing an interface that can be implemented reasonably in
both windows and posix

P.S. A good use for the library substitution approach is where your code is
supposed to be thread safe but doesn't actually use threads itself (it is
obviously part of a library) - In this case you can provide a dummy for
applications that don't actually use threads. Alternatively you could use
the templates and have a dummy and have no overhead - it depends on whether
you are delivering source or a library.

I think DEC used to use library substitution for single/multi threaded apps.

Jul 22 '05 #6
Nick,
This will significantly slow your code compared to native mutex calls which are often just macros with
no function call at all if there is no contention.
Are you saying that the overhead of the virtual member function call will
add significant overhead? Presumably the implementation member function
will contain such a native mutex call...
One responder suggested just linking to different versions which is fine but still not very efficient.
Because it still contains the above overhead? I've about ruled out this
approach, because it taints the abstraction with implementation details.
To get maximum speed the answer is templates
- parameterize everything with a class required to contain all the types and methods that you need. Default this parameter to ThreadUtil or some such.
- Have a Thread.h header that conditionally includes the appropriate system header, your platform specific thread class header and which typedefs the
platform specfic classes to ThreadUtil
- Make all the methods of your classes inline
I originally started to use templates, but after consulting the Mozilla
"Portability Guide" I decided to avoid templates and inline functions -- do
you have any comments about this, or other comments on "extreme
portability"?
This mechanism works and is efficient but be warned - different systems
model threads and their control very differently - mutex/critical section is easy but there is apparently no simple equivalent to pthread cond in
Windows.
I'm just after mutex/critical section, that's all.
P.S. A good use for the library substitution approach is where your code is supposed to be thread safe but doesn't actually use threads itself (it is
obviously part of a library) - In this case you can provide a dummy for
applications that don't actually use threads. Alternatively you could use
the templates and have a dummy and have no overhead - it depends on whether you are delivering source or a library.

I think DEC used to use library substitution for single/multi threaded apps.

Jul 22 '05 #7

"Ed Fair" <ed*****@mindspring.com> wrote in message
news:pv**************@newsread3.news.atl.earthlink .net...
Nick,
This will significantly slow your code compared to native mutex calls which
are often just macros with
no function call at all if there is no contention.


Are you saying that the overhead of the virtual member function call will
add significant overhead? Presumably the implementation member function
will contain such a native mutex call...


Whether the overhead is significant can only really depend on your app but
since a lot of people use threads because they
want to be as fast as possible the overhead may be significant - it all
depend on the app and the granularity of the locking.

The implementation of lock and unlock may not invoke a function call at all
(I'm not guessing - I've looked at some headers).
The lock call only needs to make a call if the lock is already owned. The
unlock call only needs to make a call if something another thread is
waiting.
One responder suggested just linking to different versions which is fine but
still not very efficient.


Because it still contains the above overhead? I've about ruled out this
approach, because it taints the abstraction with implementation details.


I don't see how. It makes for a messy build but the abstraction is still
clean.
To get maximum speed the answer is templates
- parameterize everything with a class required to contain all the types and
methods that you need. Default this parameter to ThreadUtil or some such. - Have a Thread.h header that conditionally includes the appropriate

system
header, your platform specific thread class header and which typedefs the platform specfic classes to ThreadUtil
- Make all the methods of your classes inline


I originally started to use templates, but after consulting the Mozilla
"Portability Guide" I decided to avoid templates and inline functions --

do you have any comments about this, or other comments on "extreme
portability"?

I cannot think of any reason to avoid these - were not talking anything
exotic here - no partial specializations - no defaults.

I don't know of any reason at all not to use inline functions. Code bloat is
a possibility but that isn't a portability issue.
This mechanism works and is efficient but be warned - different systems
model threads and their control very differently - mutex/critical section is
easy but there is apparently no simple equivalent to pthread cond in
Windows.
I'm just after mutex/critical section, that's all.


So you are creating a thread safe library of some sort?
P.S. A good use for the library substitution approach is where your code

is
supposed to be thread safe but doesn't actually use threads itself (it

is obviously part of a library) - In this case you can provide a dummy for
applications that don't actually use threads. Alternatively you could use the templates and have a dummy and have no overhead - it depends on

whether
you are delivering source or a library.

I think DEC used to use library substitution for single/multi threaded

apps.



Jul 22 '05 #8
Nick,
So you are creating a thread safe library of some sort?


Yes, it is a small static library I'm creating, for use within my
multi-threaded application only. I will apply what I learn here to a few
other static libraries that abstract other platform specific things (such as
logFile, tapeDrive, etc).

I'm maximizing my dogma here (and showing my ignorance too) because I'm "in
my first rewrite", having learned the hard way how *not* to write portable
code; my stated goal for the next version is platform independence and ease
of portability. That's why I'm trying so hard to minimize the source code
changes required upon each port. I have many source files that make up
this project, the biggest ones are becoming "platform independent", meaning
that they will not need to be "rewritten" for each port. However, they will
still at least need some tweaking... I'm guessing at least the factory
classes will have to be changed at each port, and some different includes
will be required at the top of each source file that is "platform
independent".

I've looked pretty hard for insight into this, without luck; including the
GNU Goat Book.

ed
Jul 22 '05 #9

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

Similar topics

17
by: Medi Montaseri | last post by:
Hi, Given a collection of similar but not exact entities (or products) Toyota, Ford, Buick, etc; I am contemplating using the Abstraction pattern to provide a common interface to these products....
6
by: Boogie El Aceitoso | last post by:
Hi, I'd like to have a function factory that returns objects of a class hierarchy. What's the best way to deal with the fact that different subclasses will have different constructor arguments?...
10
by: Chris Croughton | last post by:
What do people call their factory functions? 'new' is not an option (yes, it can be overloaded but has to return void*). The context is: class MyClass { public: // Factory functions...
4
by: max | last post by:
Hello, I analyze this design pattern for a long time but I do not understand how this pattern work and what the purpose is? (I looked a this site...
10
by: Mark | last post by:
I have an abstract class, and a set of classes that inherit from my abstract class. The fact that it is abstract is likely irrelevant. I have a static factory method in my abstract class that...
2
by: Stig Nielsson | last post by:
I am wondering what is the most efficient way to make a parameterized factory method, and before I start spending time on performance measurements myself, I would like to hear the NG's opinion: ...
5
by: Anders Borum | last post by:
Hello! Whilst refactoring an application, I was looking at optimizing a ModelFactory with generics. Unfortunately, the business objects created by the ModelFactory doesn't provide public...
8
by: googlegroups | last post by:
Hi, I need to parse a binary file produced by an embedded system, whose content consists in a set of events laid-out like this: <event 1<data 1<event 2<data 2... <event n<data n> Every...
8
by: Steven D'Aprano | last post by:
I'm writing a factory function that needs to use keywords in the produced function, not the factory. Here's a toy example: def factory(flag): def foo(obj, arg): if flag: # use the spam keyword...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
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...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
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...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
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,...
0
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...

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.