Here i as wild idea:

//////////

void main () {

  mutex x;
  // mutex is not a type but rather a keyword
  // x is a symbol in order to allow
  // different x in different scopes

  shared(x) int i;
  // ... or maybe use UDA ?
  // mutex x must be locked
  // in order to change i

  synchronized (x) {
    // lock x in a compiler-aware way
    i++;
    // compiler guarantees that i will not
    // be changed outside synchronized(x)
  }

}

//////////

so I tried something similar with current implementation:

//////////

import std.stdio;

void main () {

  shared(int) i1;
  auto m1 = new MyMutex();

  i1.attachMutex(m1);
  // m1 must be locked in order to modify i1
        
  // i1++;
  // should throw a compiler error

  // sharedAccess(i1)++;
  // runtime exception, m1 is not locked

  synchronized (m1) {
    sharedAccess(i1)++;
    // ok, m1 is locked
  }

}

// some generic code

import core.sync.mutex;

class MyMutex : Mutex {
  @property bool locked = false;
  @trusted void lock () {
    super.lock();
    locked = true;
  }
  @trusted void unlock () {
    locked = false;
    super.unlock();
  }
  bool tryLock () {
    bool result = super.tryLock();
    if (result)
      locked = true;
    return result;
  }
}

template unshared (T : shared(T)) {
  alias T unshared;
}

template unshared (T : shared(T)*) {
  alias T* unshared;
}

auto ref sharedAccess (T) (ref T value) {
  assert(value.attachMutex().locked);
  unshared!(T)* refVal = (cast(unshared!(T*)) &value);
  return *refVal;
}

MyMutex attachMutex (T) (T value, MyMutex mutex = null) {
  static __gshared MyMutex[T] mutexes;
  // this memory leak can be solved
  // but it's left like this to make the code simple
  synchronized if (value !in mutexes && mutex !is null)
    mutexes[value] = mutex;
  assert(mutexes[value] !is null);
  return mutexes[value];
}

//////////

and another example with methods:

//////////

import std.stdio;

class a {
  int i;
  void increment () { i++; }
}

void main () {

  auto a1 = new shared(a);
  auto m1 = new MyMutex();

  a1.attachMutex(m1);
  // m1 must be locked in order to modify a1
        
  // a1.increment();
  // compiler error

  // sharedAccess(a1).increment();
  // runtime exception, m1 is not locked

  synchronized (m1) {
    sharedAccess(a1).increment();
    // ok, m1 is locked
  }

}

// some generic code

import core.sync.mutex;

class MyMutex : Mutex {
  @property bool locked = false;
  @trusted void lock () {
    super.lock();
    locked = true;
  }
  @trusted void unlock () {
    locked = false;
    super.unlock();
  }
  bool tryLock () {
    bool result = super.tryLock();
    if (result)
      locked = true;
    return result;
  }
}

template unshared (T : shared(T)) {
  alias T unshared;
}

template unshared (T : shared(T)*) {
  alias T* unshared;
}

auto ref sharedAccess (T) (ref T value) {
  assert(value.attachMutex().locked);
  unshared!(T)* refVal = (cast(unshared!(T*)) &value);
  return *refVal;
}

MyMutex attachMutex (T) (T value, MyMutex mutex = null) {
  static __gshared MyMutex[T] mutexes;
  // this memory leak can be solved
  // but it's left like this to make the code simple
  synchronized if (value !in mutexes && mutex !is null)
    mutexes[value] = mutex;
  assert(mutexes[value] !is null);
  return mutexes[value];
}

//////////

In any case, if shared itself does not provide locking and does not fixes problems but only points them out (not to be misunderstood, I completely agree with that) then I think that assigning a mutex to the variable is a must.

Aldo latter examples already work with current implementation I like the first one (or something similar to the first one) more, it looks cleaner and leaves space for additional optimizations.


On 12.11.2012 17:14, deadalnix wrote:
Le 12/11/2012 16:00, luka8088 a écrit :
If I understood correctly there is no reason why this should not
compile ?

import core.sync.mutex;

class MyClass {
void method () {}
}

void main () {
auto myObject = new shared(MyClass);
synchronized (myObject) {
myObject.method();
}
}


D has no ownership, so the compiler can't know what
if it is safe to do so or not.

Reply via email to