[omniORB] Condition varaibles - follow up...

Ole Storm storm@ifad.dk
Thu, 21 Jan 1999 11:16:24 +0100


This is a multi-part message in MIME format.
--------------C4213DF93B80E2AAEF4EF518
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Greetings,

Yesterday I mentioned a problem with condition variables on Windows NT. To
clarify my problems I have made a small example, a simple bounded buffer
that can be accessed from one or more producer and consumer processes.

The code is attached to this mail.

When the buffer process is run on Linux everything works OK. Producers are
set to wait if the buffer is full and consumers are set to wait if the
buffer is empty. Waiting threads _are_ awakened when the state of the buffer
changes.
On Windows NT 4.0, however, a process that has been set to wait is never
awakened!!! Why is that??

Could someone _please_ try out my example and explain to me why this does
not work om WindowsNT.

Best regards,

	Ole.

---------------------------------------------------------------
Ole Storm
The Institute of Applied Computer Science (IFAD)
Forskerparken 10, DK-5230 Odense M, Denmark
Phone: +45 6315 7134, Fax: +45 6593 2999, Email: storm@ifad.dk
WWW: http://www.ifad.dk
---------------------------------------------------------------
--------------C4213DF93B80E2AAEF4EF518
Content-Type: text/plain; charset=us-ascii;
 name="buffer.idl"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="buffer.idl"


typedef short BufferItem;

interface Buffer
{
  BufferItem GetItem();
  void PutItem(in BufferItem item);
};
    

--------------C4213DF93B80E2AAEF4EF518
Content-Type: text/plain; charset=us-ascii;
 name="buffer.cc"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="buffer.cc"

#include "buffer.hh"
#include "omnithread.h"
#include <iostream.h>

#define BUF_SIZE 10

// Declaration of condition variables:
static omni_mutex cond_mutex;
static omni_condition empty_buf(&cond_mutex);
static omni_condition full_buf(&cond_mutex);

static omni_mutex mutex_region;

class Buffer_i : public virtual _sk_Buffer
// 
// Implementation of the Buffer interface
//
{
public:
  Buffer_i() : index(0) {}
  BufferItem  GetItem (  );
  void PutItem ( BufferItem );

private:
  // The fixed size buffer:
  BufferItem TheBuffer[BUF_SIZE];
  int index;
};


BufferItem
Buffer_i::GetItem()
{
  while(!index){
    // No items awailable. Wait on the condition varaible empty_buf:
    empty_buf.wait();
  }
  mutex_region.lock();
  BufferItem itm = TheBuffer[--index];
  cout << "Returned item: " << itm << "\n" << flush;
  // Signal one of the possible waiting threads on PutItem()
  full_buf.signal();
  mutex_region.unlock();
  return itm;
}

void
Buffer_i::PutItem(BufferItem it)
{
  while(index >= BUF_SIZE){
    cout << "PutItem() waiting to put an item...";
    full_buf.wait();
    if(index < BUF_SIZE)
      cout << "OK\n";
    else
      cout << "Retry\n";
  }
  mutex_region.lock();
  // OK to put an item now:
  TheBuffer[index++] = it;
  cout << "Got item: " << it << "\n";
  // Signal one of the possible waiting threads on GetItem()
  empty_buf.signal();
  mutex_region.unlock();
}


CORBA::ORB_var _the_orb;
CORBA::BOA_var _the_boa;


main(int argc, char *argv[])
{
  _the_orb = CORBA::ORB_init(argc, argv, "omniORB2");
  _the_boa = _the_orb->BOA_init(argc, argv, "omniORB2_BOA");

  Buffer_i *theBuffer = new Buffer_i();

  theBuffer->_obj_is_ready(_the_boa);

  Buffer_var buf_ref = theBuffer->_this();
  CORBA::String_var pp = _the_orb->object_to_string(buf_ref);

  cerr << pp << "\n" << flush;

  _the_boa->impl_is_ready(0);

//  // Create a file for the object reference:
//  ofstream newfile;
//  newfile.open("object.string");
//  if(newfile.good()) {
//    newfile << (char *)pp << endl;
//  }
//  else{
//    err = "Could not create file object.string\n";
//  }
//  newfile.close();
  
  return 0;
}
  

--------------C4213DF93B80E2AAEF4EF518
Content-Type: text/plain; charset=us-ascii;
 name="consumer.cc"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="consumer.cc"

#ifdef _MSC_VER
#define SLEEP(n) Sleep(n)
#else
#include <unistd.h> // For usleep()
#define SLEEP(n) usleep(1000*n)
#endif
#include <iostream.h>
#include "buffer.hh"

CORBA::ORB_var _the_orb;
CORBA::BOA_var _the_boa;

main(int argc, char *argv[])
{
  _the_orb = CORBA::ORB_init(argc, argv, "omniORB2");
  _the_boa = _the_orb->BOA_init(argc, argv, "omniORB2_BOA");

  if (argc < 2) {
    cerr << "usage: consumer <object reference> [<period>]" << endl;
    return 1;
  }
  int period = 2000;
  if (argc == 3) {
    period = atoi(argv[2]);
  }
  try {
    CORBA::Object_var obj = _the_orb->string_to_object(argv[1]);

    Buffer_var buf = Buffer::_narrow(obj);
    if(CORBA::is_nil(buf)){
      cout << "Error: Object reference not valid\n";
      exit(0);
    }

    int i=0;
    while(1){
      cout << "Trying to get an item..." << flush;
      BufferItem it = buf->GetItem();
      cout << "Got " << it << "\n";
      SLEEP(period);
    }
  }
  catch(CORBA::COMM_FAILURE& ex) {
    cerr << "Caught system exception COMM_FAILURE, unable to contact the "
         << "object." << endl;
  }
  catch(omniORB::fatalException& ex) {
    cerr << "Caught omniORB2 fatalException. This indicates a bug is caught "
         << "within omniORB2.\nPlease send a bug report.\n"
         << "The exception was thrown in file: " << ex.file() << "\n"
         << "                            line: " << ex.line() << "\n"
         << "The error message is: " << ex.errmsg() << endl;
  }
  catch(...) {
    cerr << "Caught a system exception." << endl;
  }

  return 0;
}

--------------C4213DF93B80E2AAEF4EF518
Content-Type: text/plain; charset=us-ascii;
 name="producer.cc"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="producer.cc"

#ifdef _MSC_VER
#define SLEEP(n) Sleep(n)
#else
#include <unistd.h> // For usleep()
#define SLEEP(n) usleep(1000*n)
#endif
#include <iostream.h>
#include "buffer.hh"

CORBA::ORB_var _the_orb;
CORBA::BOA_var _the_boa;

main(int argc, char *argv[])
{
  _the_orb = CORBA::ORB_init(argc, argv, "omniORB2");
  _the_boa = _the_orb->BOA_init(argc, argv, "omniORB2_BOA");

  if (argc < 2) {
    cerr << "usage: producer <object reference> [<period>]" << endl;
    return 1;
  }
  int period = 2000;
  if (argc == 3) {
    period = atoi(argv[2]);
  }
  try {
    CORBA::Object_var obj = _the_orb->string_to_object(argv[1]);

    Buffer_var buf = Buffer::_narrow(obj);
    if(CORBA::is_nil(buf)){
      cout << "Error: Object reference not valid\n";
      exit(0);
    }

    int i=0;
    while(1){
      cout << "Trying to put item " << i << "..." << flush;
      buf->PutItem(i++);
      cout << "OK\n";
      SLEEP(period);
    }
  }
  catch(CORBA::COMM_FAILURE& ex) {
    cerr << "Caught system exception COMM_FAILURE, unable to contact the "
         << "object." << endl;
  }
  catch(omniORB::fatalException& ex) {
    cerr << "Caught omniORB2 fatalException. This indicates a bug is caught "
         << "within omniORB2.\nPlease send a bug report.\n"
         << "The exception was thrown in file: " << ex.file() << "\n"
         << "                            line: " << ex.line() << "\n"
         << "The error message is: " << ex.errmsg() << endl;
  }
  catch(...) {
    cerr << "Caught a system exception." << endl;
  }

  return 0;
}

--------------C4213DF93B80E2AAEF4EF518
Content-Type: text/plain; charset=us-ascii;
 name="Makefile"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="Makefile"

#
# Win 32
#
ifeq ($(OSTYPE),win32)
# Edit these variables to reflect the location of your installation
OMNIDIR = c:/omniORB_2.6.1

CORBA_CPPFLAGS = -D__WIN32__ -D__x86__ -D__NT__ -D__OSVERSION__=4
INCDIR = -I. -I$(OMNIDIR)/include
CORBA_LIB =  wsock32.lib advapi32.lib \
            $(OMNIDIR)/lib/x86_win32/omniORB260_rt.lib \
            $(OMNIDIR)/lib/x86_win32/omnithread2_rt.lib

CXX = cl /nologo 
CXXDLL = -LD $(DEBUGDLL)
CXXFLAGS = -MT -GX $(DEBUG) $(CORBA_CPPFLAGS)
DEBUG = -Zi -MTd 
DEBUGDLL = -LDd

#DEBUG = 
#DEBUGDLL = 

COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $(INCDIR) -c

CCOUT = -Fo
CCIN = -Tp
LNKOUT = -Fe
OBJ = obj
EXE = .exe

OMNIIDL2 = $(OMNIDIR)/bin/x86_win32/omniidl2
endif

#
# Linux
#
ifeq ($(OSTYPE),Linux)
# Edit these variables to reflect the location of your installation
OMNIDIR = /local/share/lib/omniORB_2.6.1
PTHREAD_DIR = /opt/linuxthreads-0.71/

CORBA_CPPFLAGS = -D__x86__ -D__linux__ -D__OSVERSION__=2
INCDIR = -I$(PTHREAD_DIR)/include -I. -I$(OMNIDIR)/include -I$(TBDIR)/cg/include
CORBA_LIB = -lomniORB2 -lomnithread -ltcpwrapGK -lpthread -L$(OMNIDIR)/lib/i586_linux_2.0_glibc -L$(PTHREAD_DIR)/lib -L$(TBDIR)/cg/lib

CXX = g++
CXXFLAGS = -Wall -Wno-unused $(DEBUG) $(CORBA_CPPFLAGS)
DEBUG = -g 
#DEBUG = 
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $(INCDIR) -c

CCOUT = -o
CCIN = 
LNKOUT = -o
LINK = $(CXX)
OBJ = o
EXE =

OMNIIDL2 = $(OMNIDIR)/bin/i586_linux_2.0_glibc/omniidl2
endif


ifeq ($(OSTYPE),solaris2.6)
# Edit this variable to reflect the location of your installation
OMNIDIR = /local/share/lib/omniORB_2.5.0
TBDIR = /opt/toolbox
CORBA_CPPFLAGS = -DUsePthread -D_REENTRANT -D__sparc__ -D__sunos__ -D__OSVERSION__=5
INCDIR = -I. -I$(OMNIDIR)/include -I$(TBDIR)/cg/include
CORBA_LIB = -lomniORB2 -lomnithread -lpthread -lposix4 -lsocket -lnsl -ltcpwrapGK  -L. -L$(OMNIDIR)/lib/sun4_sosV_5.5 -L$(TBDIR)/cg/lib

CXX = g++
CXXFLAGS = -Wall -Wno-unused $(DEBUG) $(CORBA_CPPFLAGS)
#DEBUG = -g
DEBUG = 
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $(INCDIR) -c

CCOUT = "-o "
CCIN = 
LNKOUT = -o
LINK = $(CXX)
OBJ = o
EXE =

OMNIIDL2 = $(OMNIDIR)/bin/sun4_sosV_5.5/omniidl2
endif


all:: buffer$(EXE) producer$(EXE) consumer$(EXE) 

clean:
	rm *.$(OBJ) buffer$(EXE) consumer$(EXE) 
	rm *.hh *SK*
ifeq ($(OSTYPE),win32)
	rm *.pdb *.ilk *.opt
endif

%.$(OBJ): %.cc
	$(COMPILE.cc) $(CCIN)$< 

buffer.$(OBJ): buffer.cc bufferSK.$(OBJ)

bufferSK.cc: buffer.idl
	$(OMNIIDL2) -s SK.cc $<

buffer$(EXE): buffer.$(OBJ) bufferSK.$(OBJ)
	$(CXX) $(LNKOUT)$@ $(CXXFLAGS) $+ $(CORBA_LIB)

producer.$(OBJ): producer.cc

producer$(EXE): producer.$(OBJ) bufferSK.$(OBJ)
	$(CXX) $(LNKOUT)$@ $(CXXFLAGS) $+ $(CORBA_LIB)

consumer.$(OBJ): consumer.cc

consumer$(EXE): consumer.$(OBJ) bufferSK.$(OBJ)
	$(CXX) $(LNKOUT)$@ $(CXXFLAGS) $+ $(CORBA_LIB)



--------------C4213DF93B80E2AAEF4EF518--