BaseGDL* sem_create(EnvT *e)
  {
    SizeT nParam = e->NParam(1); // 1 is the minimal number of parameter required

    DString name;
    e->AssureStringScalarPar(0, name); // IDL accepts null-string name

    int destroyIx = e->KeywordIx("DESTROY_SEMAPHORE");
    bool destroyKWPresent = e->KeywordPresent(destroyIx);
    DLong destroy = 0;
    if (destroyKWPresent) 
    {
      destroy = (*e->GetKWAs<DLongGDL>(0))[0];
    }

    bool owner = true;
#if defined(_WIN32) && !defined(__CYGWIN__)
    // TODO: Needs error handling with name length > 256
    const char* cname = name.c_str();
    WCHAR tname[256] = {0,};

    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cname, strlen(cname), tname, 256);
    HANDLE sem = CreateSemaphoreW(NULL,1,1,tname);
    if (sem == NULL) {
	owner = false;
	return new DIntGDL(0);
    }
#else
    sem_t *sem = sem_open(name.c_str(), O_CREAT | O_EXCL, 0666, 1);
    if (sem == SEM_FAILED)
    {  // semaphore exists. make another one, locked (value=0)
      owner = false;
      if (errno == EEXIST)
      {
        sem = sem_open(name.c_str(), O_CREAT ,0666, 0);
      }
      if (sem == SEM_FAILED)
      {
        return new DIntGDL(0);
      }
    }
#endif

    // Behavior for different values of DESTROY_SEMAPHORE:
    // DESTROY_SEMAPHORE | owner    | other (== !owner)
    // ------------------+----------+-----------
    // not set           | delete   | ignore
    // != 0              | delete   | delete
    // 0                 | ignore   | ignore
    sem_data_t data;
    data.sem = sem;

    sem_set_owner(data, owner);
    sem_set_deletable(data, (!destroyKWPresent && owner) || (destroy != 0));
    sem_set_locked(data, false);

    sem_add(name, data);

    return new DIntGDL(1);
  }
Exemple #2
0
  BaseGDL* sem_create(EnvT *e)
  {
    SizeT nParam = e->NParam(1); // 1 is the minimal number of parameter required

    DString name;
    e->AssureStringScalarPar(0, name); // IDL accepts null-string name

    int destroyIx = e->KeywordIx("DESTROY_SEMAPHORE");
    bool destroyKWPresent = e->KeywordPresent(destroyIx);
    DLong destroy = 0;
    if (destroyKWPresent) 
    {
      destroy = (*e->GetKWAs<DLongGDL>(0))[0];
    }

    bool owner = true;
#ifdef _MSC_VER
    HANDLE sem = CreateSemaphore(NULL,1,1,name.c_str());
    if (sem == NULL) {
	owner = false;
	return new DIntGDL(0);
    }
#else
    sem_t *sem = sem_open(name.c_str(), O_CREAT | O_EXCL, 0666, 1);
    if (sem == SEM_FAILED)
    {
      owner = false;
      if (errno == EEXIST)
      {
        sem = sem_open(name.c_str(), 0);
      }
      if (sem == SEM_FAILED)
      {
        return new DIntGDL(0);
      }
    }
#endif

    // Behavior for different values of DESTROY_SEMAPHORE:
    // DESTROY_SEMAPHORE | owner    | other (== !owner)
    // ------------------+----------+-----------
    // not set           | delete   | ignore
    // != 0              | delete   | delete
    // 0                 | ignore   | ignore
    sem_data_t data;
    data.sem = sem;

    sem_set_owner(data, owner);
    sem_set_deletable(data, (!destroyKWPresent && owner) || (destroy != 0));
    sem_set_locked(data, false);

    sem_add(name, data);

    return new DIntGDL(1);
  }
  void sem_release(EnvT *e)
  {
    SizeT nParam = e->NParam(1);

    DString name;
    e->AssureStringScalarPar(0, name);

    sem_data_t data = sem_get_data(name, e);
    if (sem_is_locked(data))
    {
      sem_set_locked(data, false);
      sem_post(data.sem);
    }
  }
  BaseGDL* sem_lock(EnvT *e)
  {
    SizeT nParam = e->NParam(1);

    DString name;
    e->AssureStringScalarPar(0, name);

    sem_data_t &data = sem_get_data(name, e);
    if (sem_is_locked(data)) 
    {
      // lock already held
      return new DIntGDL(1);
    }
    if (sem_trywait(data.sem) == 0)
    {
      sem_set_locked(data, true);
      return new DIntGDL(1);
    }

    return new DIntGDL(0);
  }