[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1729
  • Last Modified:

MUTEX for C++ objects

Hello Experts,
I just had my first glance os MUTEX right now because I need to execute a service class in a multi-process enviroment that canot be instantiated again while it is running - like a singleton. The little I read is that whit MUTEX, when another prosses try to get a lock it will must wait, but the service that launchs the MUTEXed one must quit and return that the service canot be instantiated cause it´s already running. It´s can be done? and if it is possible how is the best way to protect the MUTEX "gate" from stay locked in case of the MUTEX object die abnormaly without release that lock?
0
rubentrancoso
Asked:
rubentrancoso
  • 6
  • 5
  • 2
  • +2
2 Solutions
 
rcarlanCommented:
Mutexes (and semaphores, events and critical sections) are multi-threading synchronisation objects. They can all be used for inter-thread communication and synchronisation.


I’ll start with critical sections because they are the simplest and easiest to understand and use. Critical sections are used for mutual exclusion synchronisation of threads belonging to the same process. They basically allow you to serialize thread access to one or more sections of code. They are constrained to a single process – i.e. if you start two instances of the same executable, each creates its own copies of the critical sections you’ve placed in your code, and threads from each process use/see only the critical sections created by the parent process.

Critical sections are very common in server/service-type code. They are used to avoid multiple threads accessing one or more resources simultaneously. They are the easiest to use, but can also easily lead to less efficient multi-threaded services when they are usually used to serialize access to large sections of code – i.e. in extreme scenarios, they are used to completely serialize access to a server. An example of an inefficient solution based on critical sections is to create a single global critical section, and each entry point (export) enters the critical section, does its stuff and then leaves the critical section. By using the same critical section across the entire server code you basically ensure that your server only services one thread/request at a time – simple but not very efficient. The key words for critical sections are “enter” and “leave” – i.e. threads enter and leave critical sections. Only one thread per process can be in any given critical section at any one time.


Mutexes are very similar to critical sections – the main difference is that mutexes can be used for mutual exclusion synchronisation of threads across processes. Basically, like critical sections, you can have only one thread being able to acquire (or lock) the mutex at a time. Mutexes are usually given a name which can be used to identify them across process boundaries. Critical sections are basically identified by a pointer to a structure. The pointer value is unique within a process but meaningless across processes. This is one of the reasons why critical sections are faster than mutexes. With mutexes you have to get the O/S involved in ‘finding’ the right instance.

Whereas with critical sections the key words were ‘enter’ and ‘leave’, with mutexes you have ‘wait’ and ‘release’. Threads ‘wait’ for the mutex to become available (i.e. ‘signalled’) and as soon as this happens, the waiting thread resumes and the mutex is placed back in an ‘unsignalled’ state. It stays unsignalled until the threat that has acquired it releases it or terminates. If multiple threads wait on the same mutex, one is released and the others keep waiting until the successful thread releases the mutex.


Semaphores are similar to mutexes but can allow more than one thread through. Whereas mutexes had just a ‘state’, semaphores also have a ‘count’. You initialise the semaphore with an initial count and until the count reaches zero, the semaphore stays signalled. Each thread that successfully acquires the semaphore decreases the count. Just like mutexes, threads ‘wait’ for the semaphore to become signalled. And just like mutexes, a thread that has successfully acquired the semaphore has to eventually release it. As opposed to mutexes, you can have more than one thread owning the semaphore at a time (the maximum number of threads allowed to own the semaphore is specified when you create the semaphore).

Finally, events are used to broadcast public signals across multiple threads (which can span multiple processes). Just like mutexes and semaphores, events have a state which can be ‘signalled’ and ‘unsignalled’. Just like semaphores, you can have multiple threads responding to an event. As opposed to semaphores, where threads acquire it one at a time, with events you can have multiple threads waiting for an event be released simultaneously. The key words are ‘set’, ‘reset’, and ‘pulse’.


In ending, it’s worth mentioning that a number of other O/S objects have signalled/unsignalled state (e.g. processes, threads, files, timers, etc). Threads can be synchronised by making them wait for any object that has a state to become signalled. For example, threads and processes become signalled when they terminate (they are unsignalled while they are still active – regardless of whether they are actually running/executing something or just sleeping/waiting).

Hopefully, you now have a better understanding of the tools at your disposal for your multi-threaded solution. It’s difficult to provide more concrete advice without more details about what you’re trying to achieve.

Radu


0
 
novitiateCommented:
you can try some thing like this...

#include <windows.h>


class Mutex
{
public:
      Mutex(char* pName){
            if(CreateMutex(0, FALSE, pName))
                  if(ERROR_ALREADY_EXISTS == GetLastError())
                        exit(0);
      }
public:
      virtual ~Mutex(){
            CloseHandle(_hMutex);
      }
private:
      HANDLE _hMutex;
};

Mutex m("My Mutex 001");

int main()
{
      Sleep(20000);
      return 0;
}

_novi_
0
 
itsmeandnobodyelseCommented:
>>>> if(CreateMutex(0, FALSE, pName))

That is wrong. CreateMutex returns a NULL handle when failing. Also you have to store the return value to _hMutex.

Though the class _novi_ has provided meets your requirements - after fixing the error - you can do it shorter by simply calling CreateMutex in your service_main function (assuming you are on a Windows platform):

void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
{
      HANDLE hMutex;
      if ((hMutex = CreateMutex(0, FALSE, SZSERVICENAME)) == NULL)
      {            
            if (GetLastError() == ERROR_ALREADY_EXISTS)
                 log(SZSERVICENAME, " already exists", GetLastError());
            else
                 log(SZSERVICENAME, " CreateMutex failed", GetLastError());
            exit(1);
      }

      ...

      CloseHandle(hMutex);
}

Regards, Alex
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
grg99Commented:
>how is the best way to protect the MUTEX "gate" from stay locked in case of the
>MUTEX object die abnormaly without release that lock?

One of the basic rules of computer science is:  Don't keep the same information in two places.  One or both of the places is likely to get out of date, and then where are you?

In this case, don't keep a separate mutex, just inquire as to the existence of the running process.  That bypasses the whole problem of the mutex getting stuck on if the process dies.


This is inevitably OS dependent, but as OS's seem to be narrowing down to Unix/Linux and Windows, it's not too hard to supply code for both these cases.



0
 
itsmeandnobodyelseCommented:
>>>> how is the best way to protect the MUTEX "gate" from stay locked in case of the
>>>> MUTEX object die abnormaly without release that lock?

In case of Windows the Mutex automatically was released if there is no process having an active handle to the Mutex. If a process terminates (abnormally or not) all open handles will be closed.

I would guess that pthread_mutex has the same behavior as I never had problems with hanging Mutexes in a VMS or UNIX environment.

Regards, Alex



0
 
rubentrancosoAuthor Commented:
The first try to implement the solution based on your posts I came across with the following problem. I canot put the MUTEX on the service class cause the overhead the infrastructure on lauching the service. Is preverable that the service only was launched if it's right that there's no other instance of it running.

The second point is that the launcher class is specified as a return class that not wait to the service to terminate. It just lauch it and return.

To follow this I thought that the right to do is to create the MUTEX on the laucher and release it on the service class but it's not the right aproach to if a care with the class responsabilities.
0
 
itsmeandnobodyelseCommented:
When talking of a mutex you should talk in terms of process and thread (actually a mutex works on threads, i. e. two different threads may block each other using a mutex) and *not* in terms of classes. If your launcher runs in a different thread or even process than the service you can't use a mutex as two different threads cannot not lock and unlock a service.

>>>> I canot put the MUTEX on the service class cause the overhead the infrastructure on lauching the service.

Actually, I don't understand your problem. What platform are you operating on? What is the 'overhead' you are talking of? Could you post some code or explain the launching issue?

Regards, Alex
0
 
rcarlanCommented:
rubentrancoso,

Base on what your requirements seem to be, I say you should consider COM.
COM already provides a framework for solving this sort of problems.

If you implement your COM server as a LocalServer32, COM will start the process the first time a client tries to create an instance of one of the COM classes the server implements. Subsequent requests (under the same user account) will reuse this process instance (i.e. will not start another).

If you want a singleton in your COM server - i.e. a COM class instance that is shared across many clients - you can do that, too. By default, each client gets its own COM class instance, but you can change this behaviour (through code).

Synchronisation across client threads is also provided by COM. You can implement your COM server as an STA (i.e. single apartment), in which case all instances of each COM class are protected against multi-threaded access (i.e. only one thread at a time can use any of the server's COM objects), or as an MTA (i.e. multi-threaded apartment), in which case it's a free for all, and you have to take care of synchronisation. Even in the latter scenario, because there is a single COM server process (per user account per machine), you don't need to use a mutex. You can get by with a critical section (which is faster).

Have a look at ATL - it's a beautifully designed framework for COM programming. You can easily wrap any ‘service’ in a COM server developed using ATL. I placed ‘service’ in between quotes because it seems you’re not really talking about a Windows service, but rather about a shared component that services certain client applications or modules that you are writing. I could be wrong, though – it wasn’t exactly clear from your message. Even if you do want a Windows service, you can use ATL and COM to implement it. Btw, with Windows services, you get one per machine (i.e. multiple simultaneous user accounts share the same instance, as opposed to a local COM server -which has one instance per user account).

Radu

0
 
itsmeandnobodyelseCommented:
>>>> Have a look at ATL - it's a beautifully designed framework for COM programming.

Hi Radu, you are the very first I heard say any positive about ATL. I am an experienced Windows programmer and I could mostly understand ATL code - though I ever tried to have not to write ATL code myself. But actually I never saw such an ugly, non-standard and bad-documented library code where 2/3 of the code are some conversions, wrappers, initializing, settings that you wouldn't need if you wouldn't use ATL. I might be unfair as I always gave a wide berth to ATL - thus never queried for 'qualities' and 'benefits' - but are you sure that *beautiful* is the right word when talking of ATL? And do you really think you need COM and ATL just to prevent a prog to be invoked twice?

Regards, Alex
0
 
grg99Commented:
I have to agree--  you just need a bleedin' interlock, like one byte.  Dragging in a few tens of megabytes of COM and ATL is a bit of overkill.
0
 
rcarlanCommented:
First of, about ATL:
Yes, it's not easy to understand and it's not very well documented. And it doesn't have any fancy wizards, either. I mean, the one available in VS6 is far from what a wizard should be and it is annoyingly sensitive to source code file locations and names (I haven't used ATL in VS.NET, yet – so I don’t know to what degree things have improved there)

You know another library that is not easy to understand, is not very well documented (at least not on MSDN and the on-line VS help) and it doesn't have wizards? I'll give you a hint: it has a three letter acronym that ends in TL and doesn't start with A :-) However, most developers I know would say that STL is beautiful and powerful, and they wouldn't consider programming in C++ without it. Few programmers have learned to use STL from the MS documentation. They relied mostly on books and articles. The same applies to ATL. Do yourself a favour – if you can still find it, buy a copy of ATL Internals by Rector and Sells. It was quite an eye opener for me, some five years ago. I believe there’s a second edition coming out this year.

ATL is very similar to STL. In fact, it was designed to integrate with STL (which is quite extraordinary considering Microsoft's reluctance to embrace STL in the first place). Both ATL and STL make extensive use of the policy-based programming technique. It's not for the fainthearted - I mean designing and implementing reusable code based on policies. Using the result is usually a breeze though, once you understand how. A lot of developers I know are very happy to use STL collections (and some have even dabbled with the STL algorithms), but they don't really understand how it all hooks together, and they don't see the incredible benefit of designing code that would integrate with STL. Well, the ATL team did, and the result is quite remarkable. If you’ve ever tried to implement COM collections manually (over existing data structures in a legacy program) and then done it through ATL, you’ll know I’m right.

You have to look beyond the ATL macros. Most of them are there in an attempt to bring ATL to the masses without compromising one of its key attributes: its leanness. ATL was designed and implemented in way that enables programmers to use it all by itself to develop COM servers. You don't even need the C runtime library. Now, that's quite an achievement in itself. Of course, in this day in age, when GBs of RAM, close to TB HDDs, and broadband Internet are taken for granted (and most developers I know don't think twice about using XML to exchange information between proprietary components), being so frugal as to try to avoid a few hundreds of KBs may seem rather excentric. But when ATL was designed, most computer users were trying to squeeze the last baud they could from their modem and phone line, in the pursuit for the elusive 56K data transfer speed.

I found it very hard myself, initially, to do ATL programming. In fact, to such a degree that I ended up writing COM servers manually – from scratch (no library). Well, initially I used MFC. But when I couldn’t afford the baggage, I tried to do it using ATL, found it daunting, and resulted in writing the nitty gritty code manually. In the process, after about two or three servers, I realised that there was a lot of boilerplate code that I was just copying and pasting from one server to the next. So, I started putting together a library to assist me in the process. When I started using template classes and macros in this library, something clicked. It all looked familiar – I had seen the concept before. So, I got ATL Internals, read it (and even the book can be quite intense at times), but a week later I was flying through my COM programming using ATL.


Now, as for using COM and ATL “just to prevent a prog to be invoked twice” – of course not. But if it’s a ‘service’ of some sort, it needs to presumably expose functionality through APIs. It then needs to deal with marshalling data and errors across process boundaries. It also needs means to provide for instantiation and clean-up, protecting against multi-threaded access to shared resources, etc. All these (and more) have been addressed with COM. And ATL makes it easy to put together a server that wraps existing code and exposes its functionality to multiple clients. .NET is another option, if you don’t mind running in a managed environment.

Radu

0
 
rcarlanCommented:
"tens of megabytes of COM and ATL" ???

grg99, have you done any COM/ATL programming yourself?

The COM server I'm currently working on is 61,440 bytes and doesn't require any third-party DLLs (not even ATL.DLL or the CRT DLLs). The only DLL it needs is its proxy/stub (another self-sufficient module, only 24,576 bytes in size).

I'm willing to agree some of what Alex has said (ATL certainly isn't the easiest framework to understand), but I have to take issue against it being bloated. Quite the contrary, it's the leanest of libraries.

Radu

0
 
itsmeandnobodyelseCommented:
>>>> ATL is very similar to STL.

I don't think you are right. STL is the main part of the C++ Standard and relatively easy to use - if you know what container classes are for, though not simply to understand how it works. But any function you could call is well documented - maybe not in VC6, but VC6 was made *before* STL became standard.

I am using STL mostly here in EE but haven't used it before as I had my own container classes and templates that were much mightier than STL. But STL isn't much difficult to use and the number of classes and functions is manageable.

STL itself doesn't use macros, only some implementations do, mostly for any 'Compatibilty Reasons' that should mean 'Uncompatibilty with other platforms'. ATL extensively uses macros. And it isn't any standard beside of a Microsoft standard. So, where do you see similarities beside of the name.

>>>> You have to look beyond the ATL macros.

Why should I? Did you ever try to debug a macro code? The macros are a big part of the problem as preprocessing nothing has to do with C++. STL uses C++  means, say templates. So, everybody who learned C++, and unterstands templates, was able to understand the principles of STL.

I made a macro library myself (1997) where some macros were implementing 20 or 30 functions and 50 lines (and more) of code. The purpose of these macros were to have a one-liner when making a class member a persistent database field. So, I needed a lot of code to move the contents of the member from database to class and vice versa, to be able o query the member, and so on. Nobody who uses that macro interface needs to *know* what these macros actually are doing. And there is the big difference to ATL. If you don't look behind the macros you are stuck as the documentation not even tells you what the return values of the ATL functions are and what are the preconditions before you could hope to successfully call an ATL function. Here in EE often people are asking why their ATL code isn't running (mostly because they forgot  an initializing call or did not convert single-byte strings to wide) and the error they got in almost all case didn't give any hint what was wrong.

No, you will not turn me to favour ATL (cause there is none of the functionalities you summarized that couldn't be done if *not* using ATL and COM) but I accept that you do and it was an interesting experience that there is at least one.

Regards, Alex


0
 
rcarlanCommented:
>>So, where do you see similarities beside of the name [between STL and ATL].

They both use the policy-based programming technique.


>>Why should I [look beyond ATL macros]?

Because ATL is all template based. The macros are there to hide the complexity of templates from programmers who are not very proficient in templates and policy-based programming.


>>the error they got in almost all case didn't give any hint what was wrong [with their ATL code]

True. Though to some extent also true about STL compilation errors. You often get three lines of an error message, generally in a totally different piece of code than where the programming error really is. This is actually one of the pitfalls of policy-based programming.


I don't have any involvement with MS or the ATL team. It makes no difference to me if you use ATL or not. I was just trying to share my experience, for what it was worth. I'm not trying to start a dispute over ATL nor do I see any benefit to get involved in one. But I am happy to answer specific questions about ATL, should there be any.

I have been doing C++ programming for 15 years. I am chief software architect for a software company. We use a lot of different technologies in our software development - different tools for different purposes. Obviously, just because a tool is good at something, doesn't mean it's the right solution for all problems. ATL works for us for COM development. We didn't find anything better. There are many experienced developers in our software development team. Selecting ATL for COM development wasn't a unilateral decision. In fact, I'd be interested to know what others are using for COM development.

Radu

0
 
rcarlanCommented:
Yeah... we kinda went off on a tangent on this one :-)
Sorry.

Radu
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 6
  • 5
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now