Running a plugin

Once a plugin has been defined, it can be started. Normally, DQCsim will do this in one way or another. There are three ways in which DQCsim can do this:

  • by spawning a process;
  • by spawning a thread within the simulation process;
  • by letting you spawn the plugin.

We'll go into this in greater depths when we get into simulation construction. For now, I'll assume that the first thing has already happened, and the process that was launched is the one that you're working on right now.

DQCsim will spawn a plugin process with a single command-line argument (in addition to the process name as per convention). This argument identifies a FIFO file or address of some kind that tells the DQCsim instance running in the plugin process how to connect to the DQCsim instance that controls the simulation. You don't need to know anything about the syntax of this argument; all you need to do is pass it to dqcs_plugin_run(), along with a plugin definition.

dqcs_plugin_run()

Executes a plugin in the current thread.

dqcs_return_t dqcs_plugin_run(
    dqcs_handle_t pdef,
    const char *simulator
)

pdef must be an appropriately populated plugin definition object. Its callback functions will be called from the current thread, from within the context of this function.

simulator must be set to the address of our endpoint of the simulator that's using the plugin; DQCsim normally passes this as the first command line argument of the plugin process.

If the plugin starts, the pdef handle is consumed by this function, regardless of whether the plugin eventually closes normally. The handle is only left alive if pdef is not a plugin definition object.

If the function fails, your process should return a nonzero exit code; if it succeeds, it should return 0. And that's it!

Some notes, though:

  • If you spawned the process manually, you're in control of how the connection endpoint string is passed. So you can do something else if you like, but keep in mind that the command-line interface won't be able to use your plugin in that case.
  • The connection endpoint is currently a FIFO file, so it cannot connect to another machine.
  • dqcs_plugin_run() is a blocking function call. If you're making some awesome plugin server that needs to be able to run multiple plugin threads at a time, you can also use the asynchronous equivalents below. This is particularly useful in case you want to construct the plugin definition in your main thread for some reason. However, you can currently only use a plugin definition once; it is deleted by dqcs_plugin_start() as well as dqcs_plugin_run().
dqcs_plugin_start()

Executes a plugin in a worker thread.

dqcs_handle_t dqcs_plugin_start(
    dqcs_handle_t pdef,
    const char *simulator
)

This function behaves the same as dqcs_plugin_log(), but is asynchronous; it always returns immediately. Of course, this means that the callbacks in pdef will be called from a different thread.

To wait for the thread to finish executing, call dqcs_plugin_wait() on the returned join handle. Alternatively you can delete the join handle object, which will detach the thread.

Note that dqcs_log_*() will only be available in the thread that the plugin actually runs in.

This function returns 0 to indicate failure to start the plugin. Otherwise, the join handle is returned.

dqcs_plugin_wait()

Waits for a plugin worker thread to finish executing.

dqcs_return_t dqcs_plugin_wait(dqcs_handle_t pjoin)

Unless the join handle is invalid, this function returns success/failure based on the result of the plugin execution. If the plugin thread is joined, the join handle is deleted.