mercredi 15 septembre 2021

Meyer's singleton pattern calls constructor twice [closed]

// Meyer's singleton pattern
struct S {
  static S& GetInstance() {
    static S s;
    return s;
  }
}

// basic singleton pattern
struct S {
  static S* s;
  static S& GetInstance() {
    if (s == nullptr) {
      s = new S();
    }
    return *s;
  }
}

I use Meyer's singleton pattern but it call S() twice. To solve this problem. I have tried basic singleton pattern and It works. I provide this S class as shared library (like libS.so). there is any thing what I missed?

Edited

I added logging in constructor. like following. I noticed client reference different address

struct S {
  S() {
    std::printf("S constructor, address:%p\n", this);
  }
}

And I use GCC5 version with std11. I have developed in multi-thread environment but We use scheduler to control only one thread run at the time.

Edited version 2

203654 col 9| common::PayloadAllocator::PayloadAllocator()                                                                                                                              
203655 col 9| common::PayloadAllocator::PayloadAllocator()

Above logging, Prove calling constructor twice

class PayloadAllocator {
...
  static PayloadAllocator& GetInstance() {
    static PayloadAllocator payload_allocator;
    return payload_allocator;
  }
...
};

PayloadAllocator::PayloadAllocator() : free_queue_() {
  std::printf("%s\n", __PRETTY_FUNCTION__);
  for (int i = 0; i < pool_size; i++) {
    mapped_type value = common::make_unique<tlm::tlm_generic_payload>();
    key_type key = value.get();
    payload_pool_.emplace(key, std::move(value));
    free_queue_.emplace(key);
  }
}

PayloadAllocator looks like above, anyway I have tested in shared library circumstance and not. this is happened when using shared library only.

Edited version 3 for Human-Compiler

Is GetInstance() defined in the header, either marked inline or just defined inline in the class body?

Yes. it is GeInstance defined in the header and just defined inline in the class body.

And is PayloadAllocator::GetInstance() called both internally inside your shared library, as well as called by the consumer of the shared library?

Yes. you're right.

// Consumer part that is out of shared library
template <typename T>
explicit PayloadBuilder(T& t, std::size_t size, const sc_dt::uint64 address)
      : payload_(nullptr) {
    ...
    payload_ = PayloadAllocator::GetInstance().Allocate();
    ...
}

// Following code is in same shared library
Payload::~Payload() {
  PayloadAllocator::GetInstance().Deallocate(payload_);
}

Payload::Payload(Payload&& other) noexcept {
  *this = std::move(other);
}

Payload& Payload::operator=(Payload&& other) noexcept {
  if (this == &other) return *this;
  PayloadAllocator::GetInstance().Deallocate(payload_);
  payload_ = other.payload_;
  other.payload_ = nullptr;
  return *this;
}

Aucun commentaire:

Enregistrer un commentaire