Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Sharing a singleton in an executable and a runtime DLL

Sharing a singleton in an executable and a runtime DLL

Scheduled Pinned Locked Moved C / C++ / MFC
helpquestiondesignxml
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Dustin Henry
    wrote on last edited by
    #1

    Hi all, I have recently run into a problem I was not expecting that stands to jeopardize quite a bit of work. Within my application I have a singleton system logging object that reads from and writes to an XML file. This application also loads several DLLs which in turn also need to be able to contribute to the system log. The problem is when the DLLs try to get a pointer to the singleton they are actually creating a new instance of the object rather than referencing the one that has already been created. This creates an obvious problem with concurrent file I/O. My question is, is there any way around this? The design of this object is such that the only interface anyone has to this object is through global macros(i.e. LOG_ERROR("error happened")), which handle accessing the singleton, meaning simply passing a pointer into the DLL at creation time is not feasible. Any help is greatly appreciated. Thanks, Dustin Henry

    S 1 Reply Last reply
    0
    • D Dustin Henry

      Hi all, I have recently run into a problem I was not expecting that stands to jeopardize quite a bit of work. Within my application I have a singleton system logging object that reads from and writes to an XML file. This application also loads several DLLs which in turn also need to be able to contribute to the system log. The problem is when the DLLs try to get a pointer to the singleton they are actually creating a new instance of the object rather than referencing the one that has already been created. This creates an obvious problem with concurrent file I/O. My question is, is there any way around this? The design of this object is such that the only interface anyone has to this object is through global macros(i.e. LOG_ERROR("error happened")), which handle accessing the singleton, meaning simply passing a pointer into the DLL at creation time is not feasible. Any help is greatly appreciated. Thanks, Dustin Henry

      S Offline
      S Offline
      Stuart Dootson
      wrote on last edited by
      #2

      Dustin Henry wrote:

      My question is, is there any way around this?

      There must be - I've done it in apps (strangely enough, it was a logging class in my app as well!). I also had the same issue you had (getting multiple instances) - I seem to remember the following making a difference:

      • Making sure that all code implementing the singleton is implemented in .cpp files, not headers
      • Using the DLL version of the C run-time

      I also implemented the thing as a monostate object - all methods were static, something like:

      class Logger
      {
      public:
      static void Log(std::string const& msg);
      private:
      Logger();
      static Logger* instance_;
      std::ostream& output;
      };

      You could then access the logger using

      Logger::Log("Hello World");

      Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

      D 1 Reply Last reply
      0
      • S Stuart Dootson

        Dustin Henry wrote:

        My question is, is there any way around this?

        There must be - I've done it in apps (strangely enough, it was a logging class in my app as well!). I also had the same issue you had (getting multiple instances) - I seem to remember the following making a difference:

        • Making sure that all code implementing the singleton is implemented in .cpp files, not headers
        • Using the DLL version of the C run-time

        I also implemented the thing as a monostate object - all methods were static, something like:

        class Logger
        {
        public:
        static void Log(std::string const& msg);
        private:
        Logger();
        static Logger* instance_;
        std::ostream& output;
        };

        You could then access the logger using

        Logger::Log("Hello World");

        Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

        D Offline
        D Offline
        Dustin Henry
        wrote on last edited by
        #3

        Hey Stuart, thanks for your help. I still couldn't get it to work so I just ended up passing in a pointer to the already created object and setting it via a macro. Not as clean as I would like but functional. Dustin

        S 1 Reply Last reply
        0
        • D Dustin Henry

          Hey Stuart, thanks for your help. I still couldn't get it to work so I just ended up passing in a pointer to the already created object and setting it via a macro. Not as clean as I would like but functional. Dustin

          S Offline
          S Offline
          Stuart Dootson
          wrote on last edited by
          #4

          I went back and had a look at the reporting implementation I wrote - I think the main difference is that I put my logger in a DLL, not the EXE. That way it's a lot easier for everything to link against it and be able to call it at run-time. However, the implementation boiled down to what I described - there's a class with a single static function allowing reporting, and purely static (i.e. single instance for the whole class) data members: Header file:

          class Reporter
          {
          public:
          Reporter();

          /// Output a message at a specified level.
          static void Report(TMessageLevel level, const std::string& message);

          /// Determine if a message level is enabled and has attached output sink(s).
          static bool Reporting(TMessageLevel level);

          private:
          static TMessageLevel level_; // Store message levels to be output - a bitmask
          static implementation-defined message_; // Output sink mechanism
          enum { ReportLevelCount = sizeof(Reporter::level_) * 8 };
          };

          C++ file:

          Reporter::Reporter()
          {
          }

          void Reporter::Report(TMessageLevel level, const std::string& message)
          {
          if (Reporting(level)) {
          message_(message);
          }
          }

          // Reporter::Reporting
          //
          // Is the specified reporting level active? OnError is treated separately to other
          // levels, as there's a separate reporting channel for errors
          bool Reporter::Reporting(TMessageLevel level)
          {
          int levelMask = (level < ReportLevelCount)?(1<

          message_ is effectively a function object that allows me to hook up the output mechanism at runtime.

          Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups