Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add moo templates to make opmon info structs with std::atomic member variables #174

Closed
wants to merge 1 commit into from

Conversation

philiprodrigues
Copy link
Contributor

Our normal codegen-ed structs (via ostructs.hpp.j2) have numeric member variables that are bare instances of the numeric type
they represent. Eg:

struct mymodule::Info {
   uint32_t a_counter;
   uint32_t another_counter;
};

We pass these structs to the operational monitoring via the get_info() function, which is typically called from a different thread than the one in which the counters are actually filled. That means we have to "shadow" each of the members of mymodule::Info with a std::atomic which is a member of MyModule, and then copy the value of each atomic into the Info object inside get_info(). (In this example, we have to add std::atomic<uint32_t> m_a_counter, m_another_counter; members to MyModule)

We can avoid this duplication by holding a mymodule::Info as a member variable of MyModule and updating the counters in that object. This in turn means that the counters in the Info object have to be atomic, ie:

struct mymodule::Info {
   std::atomic<uint32_t> a_counter;
   std::atomic<uint32_t> another_counter;
};

This PR introduces a new pair of moo templates, OpmonStructs.hpp.j2 and OpmonNljs.hpp.j2, which correspond to moo's existing ostructs.hpp.j2 and onljs2.hpp.j2. The only real change is making all member variables that have moo-type "number" into std::atomic. (We also have to do a bit of work to make the to_json() and from_json() functions play nice with the atomic
variables.)

(*.j2 files in the schema/ directory aren't currently installed by daq_install(), so we install them "manually" in CMakeLists.txt. See DUNE-DAQ/daq-cmake#44 )

To take advantage of the new-style info structs, no changes are needed to "info" schema files. But in CMakeLists.txt, call daq_codegen() for your "info" schema with the "opmon" templates, eg:

daq_codegen(mymoduleinfo.jsonnet
            myothermoduleinfo.jsonnet
            DEP_PKGS appfwk TEMPLATES appfwk/OpmonStructs.hpp.j2 appfwk/OpmonNljs.hpp.j2 )

In MyModule, add a member variable of type mymodule::Info (m_info, say) and fill/increment its members in any thread you like. get_info() can then be implemented simply as:

void
MyModule::get_info(opmonlib::InfoCollector& ci, int /*level*/)
{
  ci.add(m_info);
}

Notes: this doesn't change anything about the opmon interface. It's also completely optional, in that info structs can be left in the "old" format, with duplication, if desired.

…Intended to be useful for opmon "info" structs

Our normal codegen-ed structs (via ostructs.hpp.j2) have
numeric member variables that are bare instances of the numeric type
they represent. Eg:

```cpp
struct mymodule::Info {
   uint32_t a_counter;
   uint32_t another_counter;
};
```

We pass these structs to the operational monitoring via the
`get_info()` function, which is typically called from a different
thread than the one in which the counters are actually filled. That
means we have to "shadow" each of the members of `mymodule::Info` with
a `std::atomic` which is a member of `MyModule`, and then copy the
value of each atomic into the `Info` object inside `get_info()`. We
can avoid this duplication by holding a `mymodule::Info` as a member
variable of `MyModule` and updating the counters in that object. This
means the counters in the `Info` object have to be atomic, ie:

```cpp
struct mymodule::Info {
   std::atomic<uint32_t> a_counter;
   std::atomic<uint32_t> another_counter;
};
```

We introduce a new pair of moo templates, `OpmonStructs.hpp.j2` and
`OpmonNljs.hpp.j2`, which correspond to moo's existing
`ostructs.hpp.j2` and `onljs2.hpp.j2`. The only real change is making
all member variables that have moo-type "number" into
`std::atomic`. We also have to do a bit of work to make the
`to_json()` and `from_json()` functions play nice with the atomic
variables.

`*.j2` files in the `schema/` directory aren't currently installed by
`daq_install()`, so we install them "manually" in `CMakeLists.txt`

No changes are needed to "info" schema files. But in `CMakeLists.txt`, call `daq_codegen()` for your "info" schema with the "opmon" templates, eg:

```cmake
daq_codegen(mymoduleinfo.jsonnet
            myothermoduleinfo.jsonnet
            DEP_PKGS appfwk TEMPLATES appfwk/OpmonStructs.hpp.j2 appfwk/OpmonNljs.hpp.j2 )
```

In `MyModule`, add a member variable of type `mymodule::Info` (`m_info`, say) and
fill/increment its members in any thread you like. `get_info()` can
then be implemented simply as:

```cpp
void
MyModule::get_info(opmonlib::InfoCollector& ci, int /*level*/)
{
  ci.add(m_info);
}
```
@philiprodrigues
Copy link
Contributor Author

An example of usage can be found in DUNE-DAQ/dfmodules#71

@dingp
Copy link
Contributor

dingp commented May 19, 2022

Tested dummy approval with GitHub Actions workflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Duplication of opmon "info" struct counter variables
2 participants