Main Site Documentation

Sleeping in a Gadgeteer Driver Constructor


#1

I am writing a Gadgeteer module driver for a device I’ve breadboarded. The module includes a UART that talks to a separate microcontroller on the module, and the datasheet says that I should wait at least 3500 milliseconds after power-up before sending anything to the UART on the module, to give the other microcontroller enough time to completely initialize. There is no way for me to read whether the module is ready or not. The mainboard I’m using is a FEZ Spider.

In the Gadgeteer module driver’s constructor, I set up the ports on the socket and, as a final action before leaving the constructor, I send some initial data to the UART on the module. But I need to be sure that power has been applied for at least 3.5 seconds before sending that first chunk of data.

In the module driver’s constructor, after doing everything else before sending that first data, I am grabbing DateTime.Now, to get the elapsed time since power-up, and if that elapsed time is less than the 3500ms init time required by the module, I do a Thread.Sleep for the difference between 3500ms and the actual milliseconds already elapsed. So, for example, if 900ms have elapsed since power-up, I sleep 2600ms and then send the data to the UART on the module.

Is it okay to do a Thread.Sleep inside the Gadgeteer module driver’s constructor, for under 4 seconds? Is there a better approach or pattern to accomplish this, to ensure that the module has had enough time to initialize itself?

Thanks.


#2

Use a thread to handle the device and then you can put a sleep in the start of the thread.

If you don’t want to process the device in a thread, another option you can do is to set a FLAG that you check is set or cleared and use a thread to handle the time checking and when the time is up, set the FLAG state and let the thread exit. You main code will now run because the FLAG is now in the correct state.


#3

Thanks for your replies.

To make this work seamlessly and robustly from the user’s perspective, I would like to ensure that two conditions have been met before returning control from the constructor - or rather, before the user can use any methods or properties in this module’s class. The two conditions are:

(1) the required module initialization time has passed (a matter of waiting a minimum amount of time), and

(2) the initial data has been sent to the device, putting it into a known good initial state. This can be done immediately after (1).

The driver is presenting the user with a high-level interface to the module, so all of the underlying timing and messaging details are completely hidden. If the hardware changes in a future version and no longer has this internal initialization requirement, I don’t want the user’s source code to have to change at all. Thus, I would like to avoid requiring the user to explicitly have to call an additional initialization method before using any of the other properties or methods, just to complete this wait and send of initial data.

In the constructor, if I fire off another thread to do the waiting/sending, and set a flag that gets checked in the constructor, I’m still effectively waiting in the constructor for the time to elapse. If I don’t check it in the construction, and I don’t make the user call an explicit initialization method before doing anything else with the module, then every method and property in the driver class would need to check the flag and perform the rest of the initialization at that point. That puts an extra test in every property and method available to the user, which seems inefficient. But if I want to completely shield the user’s code from these initialization details, then checking the flag everywhere would be required.

The driver would be much smaller and cleaner if I could safely sleep in the constructor. But that’s life.


#4

@ andre.m -

Thanks.

Yes, I thought about doing this, but if the user code doesn’t remember to subscribe to the event and just starts using the driver’s methods and properties before the module is completely initialized, we run into trouble. And if I happen to fire the “ready” event before the user has a chance to subscribe to it, won’t that prevent the user from ever getting the event? I suppose I could periodically fire the event, but that seems wasteful.

I’ll puzzle on this a bit more…


#5

@ andre.m -

Thanks for your reply.

I was trying to avoid “ready” checks at the beginning of every method and property, and also trying to avoid putting the burden on the user to remember to check a “ready” flag before doing anything, especially if the next version of the module doesn’t have this requirement.

I tend to strive for Einstein’s “everything should be made as simple as possible, but no simpler,” but I guess I might be trying to make it “more simple than possible” for the user in this case.


#6

IMO, for this type of complex work, you shouldn’t do this in a constructor. This isn’t a rule, but it’s something that many developers (server, desktop, phone, etc.) tend to agree on, especially as duration or complexity go up.

The constructor can do basic initialization (or nothing).

You then have some sort of initialization method that does the real work. That method sets a flag that other methods check before performing their operations. Other operations could check for initialized state, and if not there, either do the initialization themselves, or throw an exception.

Why is this a good idea?

  • Your user (developer) has more control over when and where initialization happens.
  • Object can be constructed as a member variable, without worrying about an exception
  • Initialization can be retried without destroying the object
  • Better supports composite OO objects that may contain an instance of this class
  • Allows delayed initialization in case the module is not needed until later, potentially keeping resources free.
  • No concerns about the state of virtual functions called from base-class constructors.
  • Most discussions about “complex work” constructors fail to address the concept of resource acquisition. You’ll find plenty of examples where the acquisition is done in a separate step, and not the constructor. For example: file access.

Why is it a bad idea?

  • It’s another method to call
  • If the object is completely useless without the init function, it’s a zombie object
  • Added complexity for initializing arrays of instances of these objects

Some discussion on this:
C++, but still applies: http://stackoverflow.com/questions/3905784/what-not-to-do-in-a-constructor (you’ll see there’s contention there, and good arguments on both sides, but I think most would agree that a multi-second wait in a constructor wouldn’t be a good idea)

Again, not a hard and fast rule, but I would be personally wary of acquiring resources or doing any sort of delay in a constructor.

Pete


#7

@ andre.m and Pete Brown -

Thanks for your thoughtful replies.

My user is a “developer,” in that they are writing a C# application to make use of the module driver. However, I was hoping to allow a relatively inexperienced developer to use the module without having to read separate documentation. My goal was to use this module (along with some others) as part of a Gadgeteer training series for people who are relatively new to development. Obviously, if I can’t make it this simple, then I won’t. But I wanted to give it a try.

I guess my question about performing a delay in the constructor is less philosophical and more specific to the Gadgeteer environment. I’m trying to determine if there is some technical reason why I cannot do it. Is there some sort of timer that limits the total amount of time spent before Run gets called from Main? I don’t see evidence of this in the generated code, but perhaps a timer is set before Main ever gets called.

In the Gadgeteer world, the generated code invokes the construction of the driver objects. The user/developer just gets his/her code called after all the module constructors have finished running. The user/developer doesn’t really have control over when the constructor gets called, unless they start monkeying around with the generated code. I suppose if they leave the module out of the Gadgeteer diagram, they could just invoke the module driver’s constructor themselves, from within their application code.

Specifically, Program.generated.cs contains Main, which calls InitializeModules (where each driver’s constructor is run in sequence), and then calls the user’s ProgramStarted method. At that point, the user performs his/her own initialization, returns from ProgramStarted, and the dispatcher is started from Main by calling the Run method.

In my experience in OO development, an object constructor’s goal is to leave the object (in this case, the instance of the driver class) in a fully-initialized, known-valid, fully-usable state before returning from the constructor. If it can’t do this, it should raise an exception and the object should be considered invalid. This is a strict interpretation, but it is what gives me pause when considering supplying a separate initialization method for the user to call.

If I were to supply the user with a separate initialization method, their likely initial inclination would be to invoke it directly from their ProgramStarted method, since “that’s where initialization goes.” But all that really does is defer the module initialization time delay from InitializeModules to ProgramStarted, which are called in sequence by Main. So, pushing that call to the user code just moves the delay from one method to the next, and puts the burden on the user to remember to do it.

If the user can’t call the separate initialization method in ProgramStarted either, because that would create too much of a delay for Main calling Run to start the dispatcher, then the user has to call the initialization method in a separate thread, and catch when that thread completes (or some other event fires, perhaps by the initialization method itself) before being able to use any methods or properties in the module driver.

So far, I have used only a few off-the-shelf Gadgeteer modules, but I haven’t yet run into a module that you can’t just start using by the time the user’s ProgramStarted method is called. I don’t want to make this new module any more difficult to use than the other modules I’ve used.

The stackoverflow discussion you pointed to starts with two points that I have always considered words to live by, namely,

  1. The cardinal rule is that the constructor should yield a fully usable object.

  2. It does not mean a fully initialized object, you may defer some initialization (think lazy) as long as the user does not have to think about it.

That last phrase is important…I don’t want the user to have to think about doing separate initialization, even if some of the initialization has to be delayed. So, if I can’t delay inside the constructor, I will need to check a flag in every user-callable method and property, and perform a deferred initialization if it isn’t already done.


#8

@ andre.m -

Understood. Thanks.

Yes, I saw a timeout debug message when I placed a lengthy loop in the ProgramStarted method when I was first playing with Gadgeteer. So, there is some time limit between the start of Main and the invocation of Run (after ProgramStarted returns).


#9

I was going to say that it’s not a good idea to sleep in the constructor, but I see the GHI Ethernet_J11D driver constructor has a Thread.Sleep(500) in it.

But also notice how that driver doesn’t acquire an important resource (the networking stack) until a separate method call “UseThisNetworkInterface”

The CAN driver has an “InitializeCAN” method.

I think it all comes down to how expensive or rare the resource is.

If, from the constructor, you spin up another thread for the init, you’ll still end up in the invalid state when the constructor finishes.

I just don’t think sleeping for a second or more is a good thing to do in the constructor.

Finally, keep in mind that the constructor with the socket number is used by the designer. You need to ensure that’s not doing resource acquisition.

I looked in the Module Builder’s guide, and this is what it has to say about constructors (emphasis mine):

[quote]Each module must supply a constructor of form shown in the following example. In
this case there are two required sockets, but there could be any number of required
and optional sockets.

 // Note: A constructor summary is auto-generated by the doc builder.
 /// <summary></summary>
 /// <param name="socketNumber">The socket that this module is plugged in to.</param>
 /// <param name="socketNumberTwo">The second socket that this module is plugged in
to.</param>
 public InterestingSensor(int socketNumber, int socketNumberTwo)
 {
 }

For optional sockets, the constructor must accept the value Socket.Unused to mean
"This optional functionality is not used" (Socket.Unused is a static property defined in
the Socket class).

Modules may define additional constructors, but these will NOT be used by the
graphic designer. Modules MUST NOT have functionality in constructors that can’t
also be accessed through methods/properties.

Certain types of modules can usefully derive from some intermediate abstract
classes, such as NetworkModule, DaisyLinkModule, DisplayModule, and
SimpleGraphicsInterface. These are nested classes under Gadgeteer.Module.
Modules that use an intermediate class may need to pass values to that class as part
of each constructor that uses the base keyword. The following example shows a
DaisyLinkModule:

 /// <summary></summary>
 /// <param name="socket">The mainboard socket that has the <see cref="Relay"/> module plugged into it.</param>
 public Relay(int socketNumber)
 : base(socketNumber, 0x12, 0, 2, 2, 50, "Relay")

[/quote]

So then I went back and looked at what my MIDI module does (it’s been a while since I touched that code)

And there you go. I’m a hypocrite :slight_smile:

        public MidiModule(int socketNumber)
        {
            Socket socket = Socket.GetSocket(socketNumber, true, this, null);

            // need a UART/USART socket.
            if (!socket.SupportsType('U'))
            {
                throw new GT.Socket.InvalidSocketException("Socket '" + socketNumber + "' does not support the MIDI module. Please plug the MIDI module into a socket labeled 'U'.");
            }

            // initialize serial comms
            _serial = new GTI.Serial(
                socket,
                31250,
                GTI.Serial.SerialParity.None,
                GTI.Serial.SerialStopBits.One,
                8,
                GTI.Serial.HardwareFlowControl.NotRequired,
                this);

            ActiveSenseMode = MidiActiveSenseMode.AutomaticallyRespond;
            FilterToChannel = MidiChannel.ChannelOmni;

            AutoFlushSerialOutput = true;

            // open ze port
            _serial.Open();
            _serial.AutoReadLineEnabled = false;
        }

Going back to the module builder’s guide info, though, I’m tempted to refactor that so you can open/close the serial port using methods, and not have that happen automatically happen in the constructor.

Rambling, and likely didn’t clear anything up, but I hope it gave you some more to consider. :slight_smile:

Pete


#10

@ Pete Brown - I interpret the statement you highlighted slightly differently. I agree that your interpretation is probably more accurate based on the wording of the statement, but my interpretation is that it only applies to constructors that are not called by the designer.

Think of module drivers that use SPI they initialize the SPI classes in the constructor, just like you initialize the serial port. Now if you had alternate constructors taking more than just the sockets as arguments then the additional initialization would need to be available in separate methods as well. This would allow developers using the designer to execute the additional initialization that the designer supported constructor would not have been able to perform.


#11

@ Pete Brown -

Thanks for your analysis and examples.

Like your Midi module, I open the serial port in my constructor. This is a perfectly valid thing to do in a constructor. I am completely encapsulating the serial port within the module driver, and presenting the user’s code with only high-level properties and methods. By design, I don’t provide the user’s code with any control over opening, closing, or changing the parameters of the serial port. Everything within the module driver assumes that the port is properly configured and has been successfully opened. As far as the user’s code is concerned, there is no knowledge of what the underlying communication mechanism is. This is basic OOD, and gives me the freedom to completely change the driver internals without breaking the user’s source code.

Regarding “Modules must not have functionality in constructors that can’t also be accessed through methods/properties,” I really don’t look at my approach (or your Midi module’s approach) as providing any functionality in the constructor that isn’t provided to the user via methods and properties. It is simply encapsulating the underlying communication mechanism. So, I don’t think this admonition implies that the driver should be refactored to provide the user’s code with access to all the underlying plumbing. That defeats the purpose of encapsulating the details in the driver code.

I think the guideline is referring to the case where alternative constructors are provided in the module driver. In that case, you want the users of Gadgeteer designer to have access to anything that non-users of the designer have.


#12

@ taylorza -

I agree completely with your interpretation of the guideline. As written, the scope of the sentence it isn’t completely clear, but in context, I agree that it’s referring to the alternative, non-designer constructor case.