Handles
The API is based upon a handle system for referring to simulator data. Handles are like cross-language references or pointers: they point to a piece of data in the simulator, but don't contain it.
The usage of handles implies that the complex data structures contained within the simulator never actually leave the simulator. Instead, when the simulator needs to pass data to you, it returns a handle, which you can use to access the contents of the referred structure through a number of API calls. Similarly, when you need to pass something to the simulator, you construct an object through a number of API calls, and then pass the handle to the simulator.
Operating on handles
Handles can represent a number of different object types. Based on the type
of object the handle represents, different interfaces are supported. For
instance, ArbCmd
objects support handle
, arb
, and cmd
, while
ArbData
objects only support handle
and arb
. You can find an
exhaustive list of all handle types and the interfaces they support in the
documentation for dqcs_handle_type_t
. Note that all normal handles
support the handle
interface.
The name of the API functions directly corresponds with the name of the
interface it requires the primary handle it operates on to have: the
functions have the form dqcs_<interface>_*
.
Thread-safety
The global state that the API calls operate on is purely thread-local. This means that you can't exchange API objects/handles between threads. However, this also makes the API perfectly thread-safe.
Functions common to all handles
The following functions are available for all handle types.
dqcs_handle_delete()
Destroys the object associated with a handle.
Destroys the object associated with a handle.
dqcs_return_t dqcs_handle_delete(dqcs_handle_t handle)
Returns 0 when successful, -1 otherwise.
dqcs_handle_delete_all()
Deletes all handles for the current thread.
Deletes all handles for the current thread.
dqcs_return_t dqcs_handle_delete_all(void)
This can be used to clean stuff up at the end of main()
or before an
abort()
of some kind. If you don't clean up properly, you might get
undefined behavior or errors when DQCsim tries to do it for you.
dqcs_handle_dump()
Returns a debug dump of the object associated with the given handle.
Returns a debug dump of the object associated with the given handle.
char *dqcs_handle_dump(dqcs_handle_t handle)
On success, this returns a newly allocated string containing the
description. Free it with free()
when you're done with it to avoid memory
leaks. On failure (i.e., the handle is invalid) this returns NULL
.
dqcs_handle_leak_check()
Succeeds only if there are no live handles in the current thread.
Succeeds only if there are no live handles in the current thread.
dqcs_return_t dqcs_handle_leak_check(void)
This is intended for testing and for finding handle leaks. The error message returned when handles remain contains dumps of the first 10 remaining handles.
dqcs_handle_type()
Returns the type of object associated with the given handle.
Returns the type of object associated with the given handle.
dqcs_handle_type_t dqcs_handle_type(dqcs_handle_t handle)