GMLC-TDC / HELICS
Showing 109 of 795 files from the diff.
Other files ignored by Codecov
CHANGELOG.md has changed.
ThirdParty/units has changed.
ThirdParty/asio has changed.
docs/ROADMAP.md has changed.
CMakeLists.txt has changed.
appveyor.yml has changed.
docs/conf.py has changed.
docs/index.md has changed.
vcpkg.json has changed.
.gitmodules has changed.

@@ -61,11 +61,20 @@
Loading
61 61
        }
62 62
    }
63 63
    /** cast to a HelicsMessage object*/
64 -
    operator HelicsMessage() const { return mo; }
64 +
    operator HelicsMessage() const
65 +
    {
66 +
        return mo;
67 +
    }
65 68
    /** check if a message_object is valid*/
66 -
    bool isValid() const { return (helicsMessageIsValid(mo) == HELICS_TRUE); }
69 +
    bool isValid() const
70 +
    {
71 +
        return (helicsMessageIsValid(mo) == HELICS_TRUE);
72 +
    }
67 73
    /** get the message source endpoint name*/
68 -
    const char* source() const { return helicsMessageGetSource(mo); }
74 +
    const char* source() const
75 +
    {
76 +
        return helicsMessageGetSource(mo);
77 +
    }
69 78
    /** set the message source*/
70 79
    Message& source(const std::string& src)
71 80
    {
@@ -79,7 +88,10 @@
Loading
79 88
        return *this;
80 89
    }
81 90
    /** get the message destination */
82 -
    const char* destination() const { return helicsMessageGetDestination(mo); }
91 +
    const char* destination() const
92 +
    {
93 +
        return helicsMessageGetDestination(mo);
94 +
    }
83 95
    /** set the message destination */
84 96
    Message& destination(const std::string& dest)
85 97
    {
@@ -94,7 +106,10 @@
Loading
94 106
    }
95 107
    /** get the original message source which may be different than source if the message was
96 108
     * filtered */
97 -
    const char* originalSource() const { return helicsMessageGetOriginalSource(mo); }
109 +
    const char* originalSource() const
110 +
    {
111 +
        return helicsMessageGetOriginalSource(mo);
112 +
    }
98 113
    /** set the original source field*/
99 114
    Message& originalSource(const std::string& osrc)
100 115
    {
@@ -102,7 +117,10 @@
Loading
102 117
        return *this;
103 118
    }
104 119
    /** get the original message destination if a filter altered it*/
105 -
    const char* originalDestination() const { return helicsMessageGetOriginalDestination(mo); }
120 +
    const char* originalDestination() const
121 +
    {
122 +
        return helicsMessageGetOriginalDestination(mo);
123 +
    }
106 124
    /** set the original destination field*/
107 125
    Message& originalDestination(const std::string& odest)
108 126
    {
@@ -110,14 +128,26 @@
Loading
110 128
        return *this;
111 129
    }
112 130
    /** get the size of the message data field*/
113 -
    int size() const { return helicsMessageGetByteCount(mo); }
131 +
    int size() const
132 +
    {
133 +
        return helicsMessageGetByteCount(mo);
134 +
    }
114 135
    /** set the size of the message data field*/
115 -
    void resize(int newSize) { helicsMessageResize(mo, newSize, hThrowOnError()); }
136 +
    void resize(int newSize)
137 +
    {
138 +
        helicsMessageResize(mo, newSize, hThrowOnError());
139 +
    }
116 140
    /** reserve a certain amount of size in the message data field which is useful for the append
117 141
     * operation*/
118 -
    void reserve(int newSize) { helicsMessageReserve(mo, newSize, hThrowOnError()); }
142 +
    void reserve(int newSize)
143 +
    {
144 +
        helicsMessageReserve(mo, newSize, hThrowOnError());
145 +
    }
119 146
    /** get a pointer to the data field*/
120 -
    void* data() const { return helicsMessageGetBytesPointer(mo); }
147 +
    void* data() const
148 +
    {
149 +
        return helicsMessageGetBytesPointer(mo);
150 +
    }
121 151
    /** set the message data from a pointer and size*/
122 152
    Message& data(const void* ptr, int size)
123 153
    {
@@ -149,9 +179,15 @@
Loading
149 179
        return *this;
150 180
    }
151 181
    /** get a the data as a null terminated C string*/
152 -
    const char* c_str() const { return helicsMessageGetString(mo); }
182 +
    const char* c_str() const
183 +
    {
184 +
        return helicsMessageGetString(mo);
185 +
    }
153 186
    /** get the time of the message*/
154 -
    HelicsTime time() const { return helicsMessageGetTime(mo); }
187 +
    HelicsTime time() const
188 +
    {
189 +
        return helicsMessageGetTime(mo);
190 +
    }
155 191
    /** set the time the message should be scheduled for*/
156 192
    Message& time(HelicsTime val)
157 193
    {
@@ -170,7 +206,10 @@
Loading
170 206
        return (helicsMessageGetFlagOption(mo, flag) == HELICS_TRUE);
171 207
    }
172 208
    /** get the messageID*/
173 -
    int messageID() const { return helicsMessageGetMessageID(mo); }
209 +
    int messageID() const
210 +
    {
211 +
        return helicsMessageGetMessageID(mo);
212 +
    }
174 213
    /** set the messageID field of a message object*/
175 214
    Message& messageID(int newId)
176 215
    {
@@ -185,7 +224,10 @@
Loading
185 224
        mo = HELICS_NULL_POINTER;
186 225
        return mreturn;
187 226
    }
188 -
    void clear() { helicsMessageClear(mo, HELICS_IGNORE_ERROR); }
227 +
    void clear()
228 +
    {
229 +
        helicsMessageClear(mo, HELICS_IGNORE_ERROR);
230 +
    }
189 231
    /** generate a new message in a federate*/
190 232
    Message& newMessageObject(const Federate& fed);
191 233
@@ -378,12 +420,21 @@
Loading
378 420
        message.release();
379 421
    }
380 422
    /** get the name of the endpoint*/
381 -
    const char* getName() const { return helicsEndpointGetName(ep); }
423 +
    const char* getName() const
424 +
    {
425 +
        return helicsEndpointGetName(ep);
426 +
    }
382 427
    /** get the specified type of the endpoint*/
383 -
    const char* getType() { return helicsEndpointGetType(ep); }
428 +
    const char* getType()
429 +
    {
430 +
        return helicsEndpointGetType(ep);
431 +
    }
384 432
385 433
    /** get the interface information field of the filter*/
386 -
    const char* getInfo() const { return helicsEndpointGetInfo(ep); }
434 +
    const char* getInfo() const
435 +
    {
436 +
        return helicsEndpointGetInfo(ep);
437 +
    }
387 438
    /** set the interface information field of the filter*/
388 439
    void setInfo(const std::string& info)
389 440
    {

@@ -121,7 +121,9 @@
Loading
121 121
        /** generate the command line parser*/
122 122
        std::unique_ptr<helicsCLI11App> generateParser();
123 123
        /** process the command line arguments */
124 -
        void processArgs(std::unique_ptr<helicsCLI11App>& app, const std::string& defaultAppName);
124 +
        void processArgs(std::unique_ptr<helicsCLI11App>& app,
125 +
                         FederateInfo& fi,
126 +
                         const std::string& defaultAppName);
125 127
126 128
      protected:
127 129
        std::shared_ptr<CombinationFederate> fed;  //!< the federate created for the Player

@@ -37,8 +37,7 @@
Loading
37 37
#    include "MessageTimer.hpp"
38 38
#else
39 39
namespace helics {
40 -
class MessageTimer {
41 -
};
40 +
class MessageTimer {};
42 41
}  // namespace helics
43 42
#endif
44 43
@@ -227,7 +226,7 @@
Loading
227 226
void FederateState::setLogger(
228 227
    std::function<void(int, std::string_view, std::string_view)> logFunction)
229 228
{
230 -
    mLogManager->setLoggerFunction(logFunction);
229 +
    mLogManager->setLoggerFunction(std::move(logFunction));
231 230
}
232 231
233 232
std::unique_ptr<Message> FederateState::receive(InterfaceHandle id)
@@ -311,19 +310,20 @@
Loading
311 310
                                    InterfaceHandle handle,
312 311
                                    const std::string& key,
313 312
                                    const std::string& type,
314 -
                                    const std::string& units)
313 +
                                    const std::string& units,
314 +
                                    uint16_t flags)
315 315
{
316 316
    std::lock_guard<FederateState> plock(*this);
317 317
    // this function could be called externally in a multi-threaded context
318 318
    switch (htype) {
319 319
        case InterfaceType::PUBLICATION: {
320 320
            interfaceInformation.createPublication(handle, key, type, units);
321 -
            if (checkActionFlag(getInterfaceFlags(), required_flag)) {
321 +
            if (checkActionFlag(flags, required_flag)) {
322 322
                interfaceInformation.setPublicationProperty(handle,
323 323
                                                            defs::Options::CONNECTION_REQUIRED,
324 324
                                                            1);
325 325
            }
326 -
            if (checkActionFlag(getInterfaceFlags(), optional_flag)) {
326 +
            if (checkActionFlag(flags, optional_flag)) {
327 327
                interfaceInformation.setPublicationProperty(handle,
328 328
                                                            defs::Options::CONNECTION_OPTIONAL,
329 329
                                                            1);
@@ -341,12 +341,12 @@
Loading
341 341
                                                      defs::Options::IGNORE_UNIT_MISMATCH,
342 342
                                                      1);
343 343
            }
344 -
            if (checkActionFlag(getInterfaceFlags(), required_flag)) {
344 +
            if (checkActionFlag(flags, required_flag)) {
345 345
                interfaceInformation.setInputProperty(handle,
346 346
                                                      defs::Options::CONNECTION_REQUIRED,
347 347
                                                      1);
348 348
            }
349 -
            if (checkActionFlag(getInterfaceFlags(), optional_flag)) {
349 +
            if (checkActionFlag(flags, optional_flag)) {
350 350
                interfaceInformation.setInputProperty(handle,
351 351
                                                      defs::Options::CONNECTION_OPTIONAL,
352 352
                                                      1);
@@ -354,7 +354,21 @@
Loading
354 354
        } break;
355 355
        case InterfaceType::ENDPOINT: {
356 356
            interfaceInformation.createEndpoint(handle, key, type);
357 -
        }
357 +
            if (checkActionFlag(flags, required_flag)) {
358 +
                interfaceInformation.setEndpointProperty(handle,
359 +
                                                         defs::Options::CONNECTION_REQUIRED,
360 +
                                                         1);
361 +
            }
362 +
            if (checkActionFlag(flags, optional_flag)) {
363 +
                interfaceInformation.setEndpointProperty(handle,
364 +
                                                         defs::Options::CONNECTION_OPTIONAL,
365 +
                                                         1);
366 +
            }
367 +
            if (checkActionFlag(flags, targeted_flag)) {
368 +
                auto* ept = interfaceInformation.getEndpoint(handle);
369 +
                ept->targetedEndpoint = true;
370 +
            }
371 +
        } break;
358 372
        default:
359 373
            break;
360 374
    }
@@ -407,9 +421,7 @@
Loading
407 421
    std::optional<ActionMessage> optAct;
408 422
    switch (action.action()) {
409 423
        case CMD_REQUEST_CURRENT_TIME:
410 -
            optAct->setAction(CMD_DISCONNECT);
411 -
            optAct->dest_id = action.source_id;
412 -
            optAct->source_id = global_id.load();
424 +
            optAct = ActionMessage(CMD_DISCONNECT, global_id.load(), action.source_id);
413 425
            break;
414 426
        default:
415 427
            break;
@@ -434,6 +446,7 @@
Loading
434 446
        unlock();
435 447
        return static_cast<IterationResult>(ret);
436 448
    }
449 +
    // this function can fail try_lock gracefully
437 450
438 451
    std::lock_guard<FederateState> fedlock(*this);
439 452
    IterationResult ret;
@@ -466,7 +479,7 @@
Loading
466 479
        }
467 480
        return static_cast<IterationResult>(ret);
468 481
    }
469 -
482 +
    // this function can handle try_lock fail gracefully
470 483
    sleeplock();
471 484
    IterationResult ret;
472 485
    switch (getState()) {
@@ -546,6 +559,16 @@
Loading
546 559
#endif
547 560
        return static_cast<IterationResult>(ret);
548 561
    }
562 +
563 +
    // if this is not true then try again the core may have been handing something short so try
564 +
    // again
565 +
    if (!queueProcessing.load()) {
566 +
        std::this_thread::yield();
567 +
        if (!queueProcessing.load()) {
568 +
            return enterExecutingMode(iterate, sendRequest);
569 +
        }
570 +
    }
571 +
549 572
    // the following code is for a situation in which this method has been called multiple times
550 573
    // from different threads, which really shouldn't be done but it isn't really an error so we
551 574
    // need to deal with it.
@@ -593,7 +616,7 @@
Loading
593 616
iteration_time FederateState::requestTime(Time nextTime, IterationRequest iterate, bool sendRequest)
594 617
{
595 618
    if (try_lock()) {  // only enter this loop once per federate
596 -
        Time lastTime = timeCoord->getGrantedTime();
619 +
        const Time lastTime = timeCoord->getGrantedTime();
597 620
        events.clear();  // clear the event queue
598 621
        LOG_TRACE(timeCoord->printTimeStatus());
599 622
        // timeCoord->timeRequest (nextTime, iterate, nextValueTime (), nextMessageTime ());
@@ -712,6 +735,16 @@
Loading
712 735
        }
713 736
        return retTime;
714 737
    }
738 +
739 +
    // if this is not true then try again the core may have been handling something short so try
740 +
    // again
741 +
    if (!queueProcessing.load()) {
742 +
        std::this_thread::yield();
743 +
        if (!queueProcessing.load()) {
744 +
            return requestTime(nextTime, iterate, sendRequest);
745 +
        }
746 +
    }
747 +
    LOG_WARNING("duplicate locking attempted");
715 748
    // this would not be good practice to get into this part of the function
716 749
    // but the area must protect itself against the possibility and should return something sensible
717 750
    std::lock_guard<FederateState> fedlock(*this);
@@ -789,7 +822,14 @@
Loading
789 822
        unlock();
790 823
        return ret;
791 824
    }
792 -
825 +
    // if this is not true then try again the core may have been handling something short so try
826 +
    // again
827 +
    if (!queueProcessing.load()) {
828 +
        std::this_thread::yield();
829 +
        if (!queueProcessing.load()) {
830 +
            return genericUnspecifiedQueueProcess(busyReturn);
831 +
        }
832 +
    }
793 833
    if (busyReturn) {
794 834
        return MessageProcessingResult::BUSY;
795 835
    }
@@ -998,6 +1038,7 @@
Loading
998 1038
    auto initError = (state == HELICS_ERROR);
999 1039
    bool error_cmd{false};
1000 1040
    bool profilerActive{mProfilerActive};
1041 +
    queueProcessing.store(true);
1001 1042
    if (profilerActive) {
1002 1043
        generateProfilingMessage(true);
1003 1044
    }
@@ -1040,6 +1081,7 @@
Loading
1040 1081
    if (initError) {
1041 1082
        ret_code = MessageProcessingResult::ERROR_RESULT;
1042 1083
    }
1084 +
    queueProcessing.store(false);
1043 1085
    if (profilerActive) {
1044 1086
        generateProfilingMessage(false);
1045 1087
    }
@@ -1225,6 +1267,13 @@
Loading
1225 1267
                                    prettyPrintString(cmd),
1226 1268
                                    cmd.actionTime,
1227 1269
                                    time_granted));
1270 +
                    auto qres = processQueryActual("global_time_debugging");
1271 +
                    qres.insert(0, "TIME DEBUGGING::");
1272 +
                    LOG_WARNING(qres);
1273 +
                }
1274 +
1275 +
                if (state <= HELICS_EXECUTING) {
1276 +
                    timeCoord->processTimeMessage(cmd);
1228 1277
                }
1229 1278
                epi->addMessage(createMessageFromCommand(std::move(cmd)));
1230 1279
            }
@@ -1255,6 +1304,9 @@
Loading
1255 1304
                    mess->messageID = cmd.messageID;
1256 1305
                    mess->original_dest = eptI->key;
1257 1306
                    eptI->addMessage(std::move(mess));
1307 +
                    if (state <= HELICS_EXECUTING) {
1308 +
                        timeCoord->processTimeMessage(cmd);
1309 +
                    }
1258 1310
                }
1259 1311
                break;
1260 1312
            }
@@ -1273,6 +1325,9 @@
Loading
1273 1325
                                         subI->getSourceName(src)));
1274 1326
                }
1275 1327
            }
1328 +
            if (state <= HELICS_EXECUTING) {
1329 +
                timeCoord->processTimeMessage(cmd);
1330 +
            }
1276 1331
        } break;
1277 1332
        case CMD_WARNING:
1278 1333
            if (cmd.payload.empty()) {
@@ -1339,17 +1394,20 @@
Loading
1339 1394
            auto* subI = interfaceInformation.getInput(cmd.dest_handle);
1340 1395
            if (subI != nullptr) {
1341 1396
                if (subI->addSource(cmd.getSource(),
1342 -
                                    std::string(cmd.name()),
1397 +
                                    cmd.name(),
1343 1398
                                    cmd.getString(typeStringLoc),
1344 1399
                                    cmd.getString(unitStringLoc))) {
1345 -
                    addDependency(cmd.source_id);
1400 +
                    if (!usingGlobalTime) {
1401 +
                        addDependency(cmd.source_id);
1402 +
                    }
1346 1403
                }
1347 1404
            } else {
1348 1405
                auto* eptI = interfaceInformation.getEndpoint(cmd.dest_handle);
1349 1406
                if (eptI != nullptr) {
1350 -
                    eptI->addSourceTarget(cmd.getSource(),
1351 -
                                          std::string(cmd.name()),
1352 -
                                          cmd.getString(typeStringLoc));
1407 +
                    eptI->addSource(cmd.getSource(), cmd.name(), cmd.getString(typeStringLoc));
1408 +
                    if (!usingGlobalTime) {
1409 +
                        addDependency(cmd.source_id);
1410 +
                    }
1353 1411
                }
1354 1412
            }
1355 1413
        } break;
@@ -1357,7 +1415,9 @@
Loading
1357 1415
            auto* pubI = interfaceInformation.getPublication(cmd.dest_handle);
1358 1416
            if (pubI != nullptr) {
1359 1417
                if (pubI->addSubscriber(cmd.getSource())) {
1360 -
                    addDependent(cmd.source_id);
1418 +
                    if (!usingGlobalTime) {
1419 +
                        addDependent(cmd.source_id);
1420 +
                    }
1361 1421
                }
1362 1422
            }
1363 1423
        } break;
@@ -1365,13 +1425,15 @@
Loading
1365 1425
            auto* eptI = interfaceInformation.getEndpoint(cmd.dest_handle);
1366 1426
            if (eptI != nullptr) {
1367 1427
                if (checkActionFlag(cmd, destination_target)) {
1368 -
                    eptI->addDestinationTarget(cmd.getSource(),
1369 -
                                               std::string(cmd.name()),
1370 -
                                               cmd.getString(typeStringLoc));
1428 +
                    eptI->addDestination(cmd.getSource(), cmd.name(), cmd.getString(typeStringLoc));
1429 +
                    if (eptI->targetedEndpoint) {
1430 +
                        addDependent(cmd.source_id);
1431 +
                    }
1371 1432
                } else {
1372 -
                    eptI->addSourceTarget(cmd.getSource(),
1373 -
                                          std::string(cmd.name()),
1374 -
                                          cmd.getString(typeStringLoc));
1433 +
                    eptI->addSource(cmd.getSource(), cmd.name(), cmd.getString(typeStringLoc));
1434 +
                    if (eptI->targetedEndpoint) {
1435 +
                        addDependency(cmd.source_id);
1436 +
                    }
1375 1437
                }
1376 1438
            }
1377 1439
        } break;
@@ -1412,9 +1474,16 @@
Loading
1412 1474
                    errorString = commandErrorString(cmd.messageID);
1413 1475
                    return MessageProcessingResult::ERROR_RESULT;
1414 1476
                }
1477 +
                if (checkActionFlag(cmd, indicator_flag)) {
1478 +
                    usingGlobalTime = true;
1479 +
                    addDependent(gRootBrokerID);
1480 +
                    addDependency(gRootBrokerID);
1481 +
                    timeCoord->setAsParent(gRootBrokerID);
1482 +
                    timeCoord->globalTime = true;
1483 +
                }
1415 1484
                global_id = cmd.dest_id;
1416 1485
                interfaceInformation.setGlobalId(cmd.dest_id);
1417 -
                timeCoord->source_id = global_id;
1486 +
                timeCoord->setSourceId(global_id);
1418 1487
                return MessageProcessingResult::NEXT_STEP;
1419 1488
            }
1420 1489
            break;
@@ -1613,7 +1682,6 @@
Loading
1613 1682
    }
1614 1683
}
1615 1684
1616 -
/** set a timeProperty for a the coordinator*/
1617 1685
void FederateState::setProperty(int intProperty, int propertyVal)
1618 1686
{
1619 1687
    switch (intProperty) {
@@ -1642,7 +1710,6 @@
Loading
1642 1710
    }
1643 1711
}
1644 1712
1645 -
/** set an option Flag for a the coordinator*/
1646 1713
void FederateState::setOptionFlag(int optionFlag, bool value)
1647 1714
{
1648 1715
    switch (optionFlag) {
@@ -1740,7 +1807,6 @@
Loading
1740 1807
    }
1741 1808
}
1742 1809
1743 -
/** get a time Property*/
1744 1810
Time FederateState::getTimeProperty(int timeProperty) const
1745 1811
{
1746 1812
    switch (timeProperty) {
@@ -1756,7 +1822,6 @@
Loading
1756 1822
    }
1757 1823
}
1758 1824
1759 -
/** get an option flag value*/
1760 1825
bool FederateState::getOptionFlag(int optionFlag) const
1761 1826
{
1762 1827
    switch (optionFlag) {
@@ -1925,15 +1990,21 @@
Loading
1925 1990
        return;
1926 1991
    }
1927 1992
    std::string header;
1993 +
    auto t = grantedTime();
1994 +
    std::string timeString;
1995 +
    if (t < timeZero) {
1996 +
        timeString = fmt::format("[{}]", fedStateString(getState()));
1997 +
    } else if (t == Time::maxVal()) {
1998 +
        timeString = "[MAXTIME]";
1999 +
    } else {
2000 +
        timeString = fmt::format("[{}]", static_cast<double>(grantedTime()));
2001 +
    }
1928 2002
    if (logMessageSource.empty()) {
1929 -
        header = fmt::format("{} ({})[t={}]",
1930 -
                             name,
1931 -
                             global_id.load().baseValue(),
1932 -
                             static_cast<double>(grantedTime()));
2003 +
        header = fmt::format("{} ({}){}", name, global_id.load().baseValue(), timeString);
1933 2004
    } else if (logMessageSource.back() == ']') {
1934 2005
        header = logMessageSource;
1935 2006
    } else {
1936 -
        header = fmt::format("{}[t={}]", logMessageSource, static_cast<double>(grantedTime()));
2007 +
        header = fmt::format("{}{}", logMessageSource, timeString);
1937 2008
    }
1938 2009
1939 2010
    mLogManager->sendToLogger(level, header, message, fromRemote);
@@ -2087,18 +2158,15 @@
Loading
2087 2158
2088 2159
std::string FederateState::processQueryActual(std::string_view query) const
2089 2160
{
2090 -
    if (query == "publications") {
2091 -
        return generateStringVector(interfaceInformation.getPublications(),
2092 -
                                    [](auto& pub) { return pub->key; });
2093 -
    }
2094 -
    if (query == "inputs") {
2095 -
        return generateStringVector(interfaceInformation.getInputs(),
2096 -
                                    [](auto& inp) { return inp->key; });
2097 -
    }
2098 -
    if (query == "endpoints") {
2099 -
        return generateStringVector(interfaceInformation.getEndpoints(),
2100 -
                                    [](auto& ept) { return ept->key; });
2101 -
    }
2161 +
    auto addHeader = [this](Json::Value& base) {
2162 +
        Json::Value att = Json::objectValue;
2163 +
        att["name"] = getIdentifier();
2164 +
        att["id"] = global_id.load().baseValue();
2165 +
        att["parent"] = parent_->getGlobalId().baseValue();
2166 +
        base["attributes"] = att;
2167 +
    };
2168 +
2169 +
    auto qres = generateInterfaceQueryResults(query, interfaceInformation, addHeader);
2102 2170
    if (query == "global_flush") {
2103 2171
        return "{\"status\":true}";
2104 2172
    }
@@ -2129,9 +2197,7 @@
Loading
2129 2197
    }
2130 2198
    if (query == "current_state") {
2131 2199
        Json::Value base;
2132 -
        base["name"] = getIdentifier();
2133 -
        base["id"] = global_id.load().baseValue();
2134 -
        base["parent"] = parent_->getGlobalId().baseValue();
2200 +
        addHeader(base);
2135 2201
        base["state"] = fedStateString(state.load());
2136 2202
        base["publications"] = publicationCount();
2137 2203
        base["input"] = inputCount();
@@ -2141,19 +2207,17 @@
Loading
2141 2207
    }
2142 2208
    if (query == "global_state") {
2143 2209
        Json::Value base;
2144 -
        base["name"] = getIdentifier();
2145 -
        base["id"] = global_id.load().baseValue();
2146 -
        base["parent"] = parent_->getGlobalId().baseValue();
2210 +
        addHeader(base);
2147 2211
        base["state"] = fedStateString(state.load());
2148 2212
        return fileops::generateJsonString(base);
2149 2213
    }
2150 2214
    if (query == "global_time_debugging") {
2151 2215
        Json::Value base;
2152 -
        base["name"] = getIdentifier();
2153 -
        base["id"] = global_id.load().baseValue();
2154 -
        base["parent"] = parent_->getGlobalId().baseValue();
2216 +
        addHeader(base);
2155 2217
        base["state"] = fedStateString(state.load());
2156 -
        timeCoord->generateDebuggingTimeInfo(base);
2218 +
        if (!timeCoord->empty()) {
2219 +
            timeCoord->generateDebuggingTimeInfo(base);
2220 +
        }
2157 2221
        return fileops::generateJsonString(base);
2158 2222
    }
2159 2223
    if (query == "timeconfig") {
@@ -2193,33 +2257,26 @@
Loading
2193 2257
    }
2194 2258
    if (query == "logs") {
2195 2259
        Json::Value base;
2196 -
        base["name"] = getIdentifier();
2197 -
        base["id"] = global_id.load().baseValue();
2260 +
        addHeader(base);
2198 2261
        bufferToJson(mLogManager->getLogBuffer(), base);
2199 2262
        return fileops::generateJsonString(base);
2200 2263
    }
2201 2264
    if (query == "data_flow_graph") {
2202 2265
        Json::Value base;
2203 -
        base["name"] = getIdentifier();
2204 -
        base["id"] = global_id.load().baseValue();
2205 -
        base["parent"] = parent_->getGlobalId().baseValue();
2266 +
        addHeader(base);
2206 2267
        interfaceInformation.GenerateDataFlowGraph(base);
2207 2268
        return fileops::generateJsonString(base);
2208 2269
    }
2209 2270
    if (query == "global_time" || query == "global_status") {
2210 2271
        Json::Value base;
2211 -
        base["name"] = getIdentifier();
2212 -
        base["id"] = global_id.load().baseValue();
2213 -
        base["parent"] = parent_->getGlobalId().baseValue();
2272 +
        addHeader(base);
2214 2273
        base["granted_time"] = static_cast<double>(timeCoord->getGrantedTime());
2215 2274
        base["send_time"] = static_cast<double>(timeCoord->allowedSendTime());
2216 2275
        return fileops::generateJsonString(base);
2217 2276
    }
2218 2277
    if (query == "dependency_graph") {
2219 2278
        Json::Value base;
2220 -
        base["name"] = getIdentifier();
2221 -
        base["id"] = global_id.load().baseValue();
2222 -
        base["parent"] = parent_->getGlobalId().baseValue();
2279 +
        addHeader(base);
2223 2280
        base["dependents"] = Json::arrayValue;
2224 2281
        for (auto& dep : timeCoord->getDependents()) {
2225 2282
            base["dependents"].append(dep.baseValue());
@@ -2256,6 +2313,8 @@
Loading
2256 2313
    } else if ((query == "queries") || (query == "available_queries")) {
2257 2314
        qstring =
2258 2315
            R"("publications","inputs","logs","endpoints","subscriptions","current_state","global_state","dependencies","timeconfig","config","dependents","current_time","global_time","global_status")";
2316 +
    } else if (query == "state") {
2317 +
        qstring = fmt::format("\"{}\"", fedStateString(getState()));
2259 2318
    } else {  // the rest might need be locked to prevent a race condition
2260 2319
        if (try_lock()) {
2261 2320
            qstring = processQueryActual(query);

@@ -7,6 +7,7 @@
Loading
7 7
#pragma once
8 8
9 9
#include "ActionMessage.hpp"
10 +
#include "BaseTimeCoordinator.hpp"
10 11
#include "CoreFederateInfo.hpp"
11 12
#include "TimeDependencies.hpp"
12 13
@@ -23,119 +24,40 @@
Loading
23 24
the time coordinator manages dependencies and computes whether time can advance or enter execution
24 25
mode
25 26
*/
26 -
class ForwardingTimeCoordinator {
27 +
class ForwardingTimeCoordinator: public BaseTimeCoordinator {
27 28
  private:
28 29
    // the variables for time coordination
29 30
    DependencyInfo upstream;
30 31
    DependencyInfo downstream;
31 32
32 -
    // Core::local_federate_id parent = invalid_fed_id;  //!< the id for the parent object which
33 -
    // should also be a ForwardingTimeCoordinator
34 -
    TimeDependencies dependencies;  //!< federates which this Federate is temporally dependent on
35 -
    /// callback used to send the messages
36 -
    std::function<void(const ActionMessage&)> sendMessageFunction;
37 -
38 -
  public:
39 -
    /// the identifier for inserting into the source id field of any generated messages;
40 -
    GlobalFederateId source_id{0};
41 -
    GlobalFederateId delayedFederate{};
42 -
    /// flag indicating that the coordinator is trying to enter the exec mode
43 -
    bool checkingExec{false};
44 -
    bool executionMode{false};  //!< flag that the coordinator has entered the execution Mode
33 +
  protected:
45 34
    bool iterating{false};  //!< flag indicating that the min dependency is iterating
46 35
    bool ignoreMinFed{false};  //!< flag indicating that minFed Controls should not be used
47 -
    /// flag indicating that a restrictive time policy should be used
48 -
    bool restrictive_time_policy{false};
49 -
    bool noParent{false};  //!< indicator that the coordinator does not have parents
50 -
    bool hasDelayedTimingFederate{false};  //!< indicator that federate is using delayed timing
51 -
  private:
52 -
    bool federatesOnly{false};  //!< indicator that the forwarder only operates with federates
36 +
53 37
  public:
54 38
    ForwardingTimeCoordinator() = default;
55 39
56 -
    /** set the callback function used for the sending messages*/
57 -
    void setMessageSender(std::function<void(const ActionMessage&)> userSendMessageFunction)
58 -
    {
59 -
        sendMessageFunction = std::move(userSendMessageFunction);
60 -
    }
61 -
62 -
    /** get a list of actual dependencies*/
63 -
    std::vector<GlobalFederateId> getDependencies() const;
64 -
    /** get a reference to the dependents vector*/
65 -
    std::vector<GlobalFederateId> getDependents() const;
66 -
67 40
    /** compute updates to time values
68 41
    and send an update if needed
69 42
    */
70 -
    void updateTimeFactors();
71 -
72 -
    /** take a global id and get a pointer to the dependencyInfo for the other fed
73 -
    will be nullptr if it doesn't exist
74 -
    */
75 -
    const DependencyInfo* getDependencyInfo(GlobalFederateId ofed) const;
76 -
    /** check whether a federate is a dependency*/
77 -
    bool isDependency(GlobalFederateId ofed) const;
78 -
    /** check whether a timeCoordinator has any dependencies or dependents*/
79 -
    bool empty() const { return dependencies.empty(); }
43 +
    virtual bool updateTimeFactors() override;
80 44
81 45
  private:
82 46
    void transmitTimingMessagesUpstream(ActionMessage& msg) const;
83 47
    void transmitTimingMessagesDownstream(ActionMessage& msg,
84 48
                                          GlobalFederateId skipFed = GlobalFederateId{}) const;
85 -
    /** generate a timeRequest message based on the dependency info data*/
86 -
    ActionMessage generateTimeRequest(const DependencyInfo& dep, GlobalFederateId fed) const;
87 49
88 50
  public:
89 -
    /** process a message related to time
90 -
    @return a message_process_result if it did anything
91 -
    */
92 -
    bool processTimeMessage(const ActionMessage& cmd);
93 -
94 -
    /** process a dependency update message*/
95 -
    void processDependencyUpdateMessage(const ActionMessage& cmd);
96 -
    /** add a federate dependency
97 -
    @return true if it was actually added, false if the federate was already present
98 -
    */
99 -
    bool addDependency(GlobalFederateId fedID);
100 -
    /** add a dependent federate
101 -
    @return true if it was actually added, false if the federate was already present
102 -
    */
103 -
    bool addDependent(GlobalFederateId fedID);
104 -
    /** remove a dependency
105 -
    @param fedID the identifier of the federate to remove*/
106 -
    void removeDependency(GlobalFederateId fedID);
107 -
    /** remove a dependent
108 -
    @param fedID the identifier of the federate to remove*/
109 -
    void removeDependent(GlobalFederateId fedID);
110 -
111 -
    void setAsChild(GlobalFederateId fedID);
112 -
    void setAsParent(GlobalFederateId fedID);
113 -
114 -
    /** disconnect*/
115 -
    void disconnect();
116 51
    /** check if entry to the executing state can be granted*/
117 -
    MessageProcessingResult checkExecEntry();
118 -
119 -
    /** function to enter the exec Mode
120 -
     */
121 -
    void enteringExecMode();
52 +
    virtual MessageProcessingResult
53 +
        checkExecEntry(GlobalFederateId triggerFed = GlobalFederateId{}) override;
122 54
123 55
    /** generate a string with the current time status*/
124 -
    std::string printTimeStatus() const;
56 +
    virtual std::string printTimeStatus() const override;
125 57
    /** generate debugging time information*/
126 -
    void generateDebuggingTimeInfo(Json::Value& base) const;
58 +
    virtual void generateDebuggingTimeInfo(Json::Value& base) const override;
127 59
128 -
    /** check if there are any active Time dependencies*/
129 -
    bool hasActiveTimeDependencies() const;
130 60
    /** get the current next time*/
131 -
    Time getNextTime() const { return downstream.next; }
132 -
    /** get a count of the active dependencies*/
133 -
    int dependencyCount() const;
134 -
    /** get a count of the active dependencies*/
135 -
    GlobalFederateId getMinDependency() const;
136 -
137 -
    /** grant timeout check
138 -
    @return a json Object with debugging info if empty nothing is logged*/
139 -
    Json::Value grantTimeoutCheck(const ActionMessage& cmd);
61 +
    virtual Time getNextTime() const override { return downstream.next; }
140 62
};
141 63
}  // namespace helics

@@ -25,10 +25,22 @@
Loading
25 25
namespace helics {
26 26
27 27
namespace detail {
28 -
    constexpr size_t getBinaryLength(double /*val*/) { return 16; }
29 -
    constexpr size_t getBinaryLength(std::int64_t /*val*/) { return 16; }
30 -
    constexpr size_t getBinaryLength(std::complex<double> /*val*/) { return 24; }
31 -
    inline size_t getBinaryLength(std::string_view val) { return val.size() + 8; }
28 +
    constexpr size_t getBinaryLength(double /*val*/)
29 +
    {
30 +
        return 16;
31 +
    }
32 +
    constexpr size_t getBinaryLength(std::int64_t /*val*/)
33 +
    {
34 +
        return 16;
35 +
    }
36 +
    constexpr size_t getBinaryLength(std::complex<double> /*val*/)
37 +
    {
38 +
        return 24;
39 +
    }
40 +
    inline size_t getBinaryLength(std::string_view val)
41 +
    {
42 +
        return val.size() + 8;
43 +
    }
32 44
    inline size_t getBinaryLength(const std::vector<double>& val)
33 45
    {
34 46
        return val.size() * sizeof(double) + 8;
@@ -38,7 +50,10 @@
Loading
38 50
        return size * sizeof(double) + 8;
39 51
    }
40 52
41 -
    inline size_t getBinaryLength(const NamedPoint& np) { return np.name.size() + 16; }
53 +
    inline size_t getBinaryLength(const NamedPoint& np)
54 +
    {
55 +
        return np.name.size() + 16;
56 +
    }
42 57
43 58
    inline size_t getBinaryLength(const std::vector<std::complex<double>>& cv)
44 59
    {

@@ -7,8 +7,12 @@
Loading
7 7
8 8
#include "logging.hpp"
9 9
10 +
#include "gmlc/utilities/string_viewConversion.h"
10 11
#include "gmlc/utilities/string_viewOps.h"
11 12
13 +
#include <map>
14 +
#include <unordered_map>
15 +
12 16
namespace helics {
13 17
extern const std::unordered_map<std::string, int> gLogLevelMap{
14 18
    {"none", HELICS_LOG_LEVEL_NO_PRINT},
@@ -60,7 +64,35 @@
Loading
60 64
    if (res != gLogLevelMap.end()) {
61 65
        return static_cast<LogLevels>(res->second);
62 66
    }
63 -
    return static_cast<LogLevels>(-999999);
67 +
    if (level.compare(0, 9, "loglevel_") == 0) {
68 +
        return static_cast<LogLevels>(
69 +
            gmlc::utilities::numeric_conversion<int>(level.substr(9), -999999));
70 +
    } else {
71 +
        return static_cast<LogLevels>(-999999);
72 +
    }
73 +
}
74 +
75 +
const std::map<LogLevels, std::string_view> levelMaps{{static_cast<LogLevels>(-999999), "no_print"},
76 +
                                                      {LogLevels::NO_PRINT, "no_print"},
77 +
                                                      {LogLevels::ERROR_LEVEL, "error"},
78 +
                                                      {LogLevels::PROFILING, "profiling"},
79 +
                                                      {LogLevels::WARNING, "warning"},
80 +
                                                      {LogLevels::SUMMARY, "summary"},
81 +
                                                      {LogLevels::CONNECTIONS, "connections"},
82 +
                                                      {LogLevels::INTERFACES, "interfaces"},
83 +
                                                      {LogLevels::TIMING, "timing"},
84 +
                                                      {LogLevels::DATA, "data"},
85 +
                                                      {LogLevels::DEBUG, "debug"},
86 +
                                                      {LogLevels::TRACE, "trace"}};
87 +
88 +
std::string logLevelToString(LogLevels level)
89 +
{
90 +
    auto res = levelMaps.find(level);
91 +
    if (res != levelMaps.end()) {
92 +
        return std::string(res->second);
93 +
    }
94 +
    std::string ret = "loglevel_" + std::to_string(static_cast<int>(level));
95 +
    return ret;
64 96
}
65 97
66 98
}  // namespace helics

@@ -17,7 +17,7 @@
Loading
17 17
18 18
static constexpr char invalidFilterString[] = "The given filter object is not valid";
19 19
20 -
/** this is a random identifier put in place when the federate or core or broker gets created*/
20 +
/** this is a random identifier put in place for validating filters*/
21 21
static const int filterValidationIdentifier = 0xEC26'0127;
22 22
23 23
static helics::FilterObject* getFilterObj(HelicsFilter filt, HelicsError* err)
@@ -78,7 +78,6 @@
Loading
78 78
79 79
HelicsFilter helicsFederateRegisterGlobalFilter(HelicsFederate fed, HelicsFilterTypes type, const char* name, HelicsError* err)
80 80
{
81 -
    // now generate a generic subscription
82 81
    auto fedObj = getFedSharedPtr(fed, err);
83 82
    if (!fedObj) {
84 83
        return nullptr;
@@ -505,7 +504,7 @@
Loading
505 504
}
506 505
507 506
void helicsFilterSetCustomCallback(HelicsFilter filt,
508 -
                                   void (*filtCall)(HelicsMessage message, void* userData),
507 +
                                   HelicsMessage (*filtCall)(HelicsMessage message, void* userData),
509 508
                                   void* userdata,
510 509
                                   HelicsError* err)
511 510
{
@@ -521,9 +520,12 @@
Loading
521 520
    }
522 521
    auto op = std::make_shared<helics::CustomMessageOperator>();
523 522
    op->setMessageFunction([filtCall, userdata](std::unique_ptr<helics::Message> message) {
524 -
        auto* ms = createAPIMessage(message);
523 +
        HelicsMessage ms = createAPIMessage(message);
525 524
        if (filtCall != nullptr) {
526 -
            filtCall(ms, userdata);
525 +
            ms = filtCall(ms, userdata);
526 +
        }
527 +
        if (ms != nullptr && reinterpret_cast<helics::Message*>(ms) != message.get()) {
528 +
            return getMessageUniquePtr(ms, nullptr);
527 529
        }
528 530
        return message;
529 531
    });

@@ -9,6 +9,7 @@
Loading
9 9
#include "../core/coreTypeOperations.hpp"
10 10
#include "../helics.hpp"
11 11
#include "gmlc/concurrency/TripWire.hpp"
12 +
#include "helicsCallbacks.h"
12 13
#include "helicsCore.h"
13 14
#include "internal/api_objects.h"
14 15
@@ -1064,6 +1065,79 @@
Loading
1064 1065
    // LCOV_EXCL_STOP
1065 1066
}
1066 1067
1068 +
void helicsFederateSetTimeRequestEntryCallback(
1069 +
    HelicsFederate fed,
1070 +
    void (*requestTimeEntry)(HelicsTime currentTime, HelicsTime requestTime, HelicsBool iterating, void* userdata),
1071 +
    void* userdata,
1072 +
    HelicsError* err)
1073 +
{
1074 +
    auto* fedptr = getFed(fed, err);
1075 +
    if (fedptr == nullptr) {
1076 +
        return;
1077 +
    }
1078 +
1079 +
    try {
1080 +
        if (requestTimeEntry == nullptr) {
1081 +
            fedptr->setTimeRequestEntryCallback({});
1082 +
        } else {
1083 +
            fedptr->setTimeRequestEntryCallback(
1084 +
                [requestTimeEntry, userdata](helics::Time currentTime, helics::Time requestTime, bool iterating) {
1085 +
                    requestTimeEntry(currentTime, requestTime, (iterating) ? HELICS_TRUE : HELICS_FALSE, userdata);
1086 +
                });
1087 +
        }
1088 +
    }
1089 +
    catch (...) {  // LCOV_EXCL_LINE
1090 +
        helicsErrorHandler(err);  // LCOV_EXCL_LINE
1091 +
    }
1092 +
}
1093 +
1094 +
void helicsFederateSetStateChangeCallback(HelicsFederate fed,
1095 +
                                          void (*stateChange)(HelicsFederateState newState, HelicsFederateState oldState, void* userdata),
1096 +
                                          void* userdata,
1097 +
                                          HelicsError* err)
1098 +
{
1099 +
    auto* fedptr = getFed(fed, err);
1100 +
    if (fedptr == nullptr) {
1101 +
        return;
1102 +
    }
1103 +
1104 +
    try {
1105 +
        if (stateChange == nullptr) {
1106 +
            fedptr->setModeUpdateCallback({});
1107 +
        } else {
1108 +
            fedptr->setModeUpdateCallback([stateChange, userdata](helics::Federate::Modes newMode, helics::Federate::Modes oldMode) {
1109 +
                stateChange(modeEnumConversions.at(newMode), modeEnumConversions.at(oldMode), userdata);
1110 +
            });
1111 +
        }
1112 +
    }
1113 +
    catch (...) {  // LCOV_EXCL_LINE
1114 +
        helicsErrorHandler(err);  // LCOV_EXCL_LINE
1115 +
    }
1116 +
}
1117 +
1118 +
void helicsFederateSetTimeRequestReturnCallback(HelicsFederate fed,
1119 +
                                                void (*requestTimeReturn)(HelicsTime newTime, HelicsBool iterating, void* userdata),
1120 +
                                                void* userdata,
1121 +
                                                HelicsError* err)
1122 +
{
1123 +
    auto* fedptr = getFed(fed, err);
1124 +
    if (fedptr == nullptr) {
1125 +
        return;
1126 +
    }
1127 +
1128 +
    try {
1129 +
        if (requestTimeReturn == nullptr) {
1130 +
            fedptr->setTimeRequestReturnCallback({});
1131 +
        } else {
1132 +
            fedptr->setTimeRequestReturnCallback([requestTimeReturn, userdata](helics::Time newTime, bool iterating) {
1133 +
                requestTimeReturn(newTime, (iterating) ? HELICS_TRUE : HELICS_FALSE, userdata);
1134 +
            });
1135 +
        }
1136 +
    }
1137 +
    catch (...) {  // LCOV_EXCL_LINE
1138 +
        helicsErrorHandler(err);  // LCOV_EXCL_LINE
1139 +
    }
1140 +
}
1067 1141
const char* helicsFederateGetName(HelicsFederate fed)
1068 1142
{
1069 1143
    auto* fedObj = getFed(fed, nullptr);

@@ -56,9 +56,15 @@
Loading
56 56
        return true;
57 57
    }
58 58
59 -
    bool ZmqRequestSets::waiting() const { return (!active_routes.empty()); }
59 +
    bool ZmqRequestSets::waiting() const
60 +
    {
61 +
        return (!active_routes.empty());
62 +
    }
60 63
61 -
    bool ZmqRequestSets::hasMessages() const { return (!Responses.empty()); }
64 +
    bool ZmqRequestSets::hasMessages() const
65 +
    {
66 +
        return (!Responses.empty());
67 +
    }
62 68
63 69
    int ZmqRequestSets::checkForMessages()
64 70
    {

@@ -0,0 +1,63 @@
Loading
1 +
/*
2 +
Copyright (c) 2017-2022,
3 +
Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable
4 +
Energy, LLC.  See the top-level NOTICE for additional details. All rights reserved.
5 +
SPDX-License-Identifier: BSD-3-Clause
6 +
*/
7 +
#pragma once
8 +
9 +
#include "ActionMessage.hpp"
10 +
#include "BaseTimeCoordinator.hpp"
11 +
#include "CoreFederateInfo.hpp"
12 +
#include "TimeDependencies.hpp"
13 +
14 +
#include "json/forwards.h"
15 +
#include <atomic>
16 +
#include <functional>
17 +
#include <string>
18 +
#include <utility>
19 +
#include <vector>
20 +
21 +
namespace helics {
22 +
23 +
/** class implementing a global time coordination in a non distributed fashion
24 +
 */
25 +
class GlobalTimeCoordinator: public BaseTimeCoordinator {
26 +
  private:
27 +
    // the variables for time coordination
28 +
    Time currentMinTime{Time::minVal()};
29 +
    TimeState currentTimeState{TimeState::initialized};
30 +
    Time nextEvent{Time::maxVal()};
31 +
32 +
  protected:
33 +
    bool iterating{false};  //!< flag indicating that the min dependency is iterating
34 +
35 +
  public:
36 +
    GlobalTimeCoordinator() = default;
37 +
38 +
    /** compute updates to time values
39 +
    and send an update if needed
40 +
    */
41 +
    virtual bool updateTimeFactors() override;
42 +
43 +
  private:
44 +
    void transmitTimingMessagesUpstream(ActionMessage& msg) const;
45 +
    void transmitTimingMessagesDownstream(ActionMessage& msg,
46 +
                                          GlobalFederateId skipFed = GlobalFederateId{}) const;
47 +
48 +
    void sendTimeUpdateRequest(Time triggerTime);
49 +
50 +
  public:
51 +
    /** check if entry to the executing state can be granted*/
52 +
    virtual MessageProcessingResult
53 +
        checkExecEntry(GlobalFederateId triggerFed = GlobalFederateId{}) override;
54 +
55 +
    /** generate a string with the current time status*/
56 +
    virtual std::string printTimeStatus() const override;
57 +
    /** generate debugging time information*/
58 +
    virtual void generateDebuggingTimeInfo(Json::Value& base) const override;
59 +
60 +
    /** get the current next time*/
61 +
    virtual Time getNextTime() const override { return currentMinTime; }
62 +
};
63 +
}  // namespace helics

@@ -0,0 +1,456 @@
Loading
1 +
/*
2 +
Copyright (c) 2017-2022,
3 +
Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC.  See the top-level NOTICE for
4 +
additional details. All rights reserved.
5 +
SPDX-License-Identifier: BSD-3-Clause
6 +
*/
7 +
8 +
#include "../application_api/TranslatorOperations.hpp"
9 +
#include "../core/core-exceptions.hpp"
10 +
#include "../helics.hpp"
11 +
#include "MessageFederate.h"
12 +
#include "Translators.h"
13 +
#include "helicsCallbacks.h"
14 +
#include "internal/api_objects.h"
15 +
16 +
#include <memory>
17 +
#include <mutex>
18 +
19 +
static constexpr char invalidTranslatorString[] = "The given translator object is not valid";
20 +
21 +
/** this is a random identifier for validating translators*/
22 +
static const int translatorValidationIdentifier = 0xB37C'352E;
23 +
24 +
static helics::TranslatorObject* getTranslatorObj(HelicsTranslator trans, HelicsError* err)
25 +
{
26 +
    HELICS_ERROR_CHECK(err, nullptr);
27 +
    if (trans == nullptr) {
28 +
        assignError(err, HELICS_ERROR_INVALID_OBJECT, invalidTranslatorString);
29 +
        return nullptr;
30 +
    }
31 +
    auto* tObj = reinterpret_cast<helics::TranslatorObject*>(trans);
32 +
    if (tObj->valid != translatorValidationIdentifier) {
33 +
        assignError(err, HELICS_ERROR_INVALID_OBJECT, invalidTranslatorString);
34 +
        return nullptr;
35 +
    }
36 +
    return tObj;
37 +
}
38 +
39 +
// fed is assumed to be valid here
40 +
static inline HelicsTranslator federateAddTranslator(HelicsFederate fed, std::unique_ptr<helics::TranslatorObject> trans)
41 +
{
42 +
    auto* fedObj = reinterpret_cast<helics::FedObject*>(fed);
43 +
    trans->valid = translatorValidationIdentifier;
44 +
    HelicsTranslator ret = trans.get();
45 +
    fedObj->translators.push_back(std::move(trans));
46 +
    return ret;
47 +
}
48 +
49 +
// core is assumed to be valid here
50 +
static inline HelicsTranslator coreAddTranslator(HelicsCore core, std::unique_ptr<helics::TranslatorObject> trans)
51 +
{
52 +
    auto* coreObj = reinterpret_cast<helics::CoreObject*>(core);
53 +
    trans->valid = translatorValidationIdentifier;
54 +
    HelicsTranslator ret = trans.get();
55 +
    coreObj->translators.push_back(std::move(trans));
56 +
    return ret;
57 +
}
58 +
59 +
HELICS_EXPORT HelicsTranslator helicsFederateRegisterTranslator(HelicsFederate fed,
60 +
                                                                HelicsTranslatorTypes type,
61 +
                                                                const char* name,
62 +
                                                                HelicsError* err)
63 +
{
64 +
    // now generate a generic subscription
65 +
    auto fedObj = getFedSharedPtr(fed, err);
66 +
    if (!fedObj) {
67 +
        return nullptr;
68 +
    }
69 +
70 +
    try {
71 +
        auto trans = std::make_unique<helics::TranslatorObject>();
72 +
        trans->transPtr = &fedObj->registerTranslator(type, AS_STRING(name));
73 +
        trans->fedptr = std::move(fedObj);
74 +
        trans->custom = (type == HELICS_TRANSLATOR_TYPE_CUSTOM);
75 +
        return federateAddTranslator(fed, std::move(trans));
76 +
    }
77 +
    catch (...) {
78 +
        helicsErrorHandler(err);
79 +
    }
80 +
    return nullptr;
81 +
}
82 +
83 +
HelicsTranslator helicsFederateRegisterGlobalTranslator(HelicsFederate fed, HelicsTranslatorTypes type, const char* name, HelicsError* err)
84 +
{
85 +
    auto fedObj = getFedSharedPtr(fed, err);
86 +
    if (!fedObj) {
87 +
        return nullptr;
88 +
    }
89 +
90 +
    try {
91 +
        auto trans = std::make_unique<helics::TranslatorObject>();
92 +
        trans->transPtr = &fedObj->registerGlobalTranslator(type, AS_STRING(name));
93 +
        trans->fedptr = std::move(fedObj);
94 +
        trans->custom = (type == HELICS_TRANSLATOR_TYPE_CUSTOM);
95 +
        return federateAddTranslator(fed, std::move(trans));
96 +
    }
97 +
    catch (...) {
98 +
        helicsErrorHandler(err);
99 +
    }
100 +
    return nullptr;
101 +
}
102 +
103 +
HelicsTranslator helicsCoreRegisterTranslator(HelicsCore cr, HelicsTranslatorTypes type, const char* name, HelicsError* err)
104 +
{
105 +
    auto core = getCoreSharedPtr(cr, err);
106 +
    if (!core) {
107 +
        return nullptr;
108 +
    }
109 +
    try {
110 +
        auto trans = std::make_unique<helics::TranslatorObject>();
111 +
112 +
        trans->mTrans = std::make_unique<helics::Translator>(core.get(), AS_STRING(name));
113 +
        trans->mTrans->setTranslatorType(type);
114 +
        trans->transPtr = trans->mTrans.get();
115 +
        trans->corePtr = std::move(core);
116 +
        trans->custom = (type == HELICS_TRANSLATOR_TYPE_CUSTOM);
117 +
        return coreAddTranslator(cr, std::move(trans));
118 +
    }
119 +
    catch (...) {
120 +
        helicsErrorHandler(err);
121 +
    }
122 +
    return nullptr;
123 +
}
124 +
125 +
static constexpr char invalidTransName[] = "the specified Translator name is not recognized";
126 +
static constexpr char invalidTransIndex[] = "the specified Translator index is not valid";
127 +
128 +
HelicsTranslator helicsFederateGetTranslator(HelicsFederate fed, const char* name, HelicsError* err)
129 +
{
130 +
    auto fedObj = getFedSharedPtr(fed, err);
131 +
    if (!fedObj) {
132 +
        return nullptr;
133 +
    }
134 +
    CHECK_NULL_STRING(name, nullptr);
135 +
    try {
136 +
        auto& id = fedObj->getTranslator(name);
137 +
        if (!id.isValid()) {
138 +
            err->error_code = HELICS_ERROR_INVALID_ARGUMENT;
139 +
            err->message = invalidTransName;
140 +
            return nullptr;
141 +
        }
142 +
        auto trans = std::make_unique<helics::TranslatorObject>();
143 +
        trans->transPtr = &id;
144 +
        trans->fedptr = std::move(fedObj);
145 +
        return federateAddTranslator(fed, std::move(trans));
146 +
    }
147 +
    // LCOV_EXCL_START
148 +
    catch (...) {
149 +
        helicsErrorHandler(err);
150 +
        return nullptr;
151 +
    }
152 +
    // LCOV_EXCL_STOP
153 +
}
154 +
155 +
int helicsFederateGetTranslatorCount(HelicsFederate fed)
156 +
{
157 +
    auto* fedObj = getFed(fed, nullptr);
158 +
    if (fedObj == nullptr) {
159 +
        return 0;
160 +
    }
161 +
    return fedObj->getTranslatorCount();
162 +
}
163 +
164 +
HelicsTranslator helicsFederateGetTranslatorByIndex(HelicsFederate fed, int index, HelicsError* err)
165 +
{
166 +
    auto fedObj = getFedSharedPtr(fed, err);
167 +
    if (!fedObj) {
168 +
        return nullptr;
169 +
    }
170 +
    try {
171 +
        auto& id = fedObj->getTranslator(index);
172 +
        if (!id.isValid()) {
173 +
            err->error_code = HELICS_ERROR_INVALID_ARGUMENT;
174 +
            err->message = invalidTransIndex;
175 +
            return nullptr;
176 +
        }
177 +
        auto trans = std::make_unique<helics::TranslatorObject>();
178 +
        trans->transPtr = &id;
179 +
        trans->fedptr = std::move(fedObj);
180 +
        return federateAddTranslator(fed, std::move(trans));
181 +
    }
182 +
    // LCOV_EXCL_START
183 +
    catch (...) {
184 +
        helicsErrorHandler(err);
185 +
        return nullptr;
186 +
    }
187 +
    // LCOV_EXCL_STOP
188 +
}
189 +
190 +
static helics::Translator* getTranslator(HelicsTranslator trans, HelicsError* err)
191 +
{
192 +
    auto* fObj = getTranslatorObj(trans, err);
193 +
    if (fObj == nullptr) {
194 +
        return nullptr;
195 +
    }
196 +
    return fObj->transPtr;
197 +
}
198 +
199 +
HelicsBool helicsTranslatorIsValid(HelicsTranslator trans)
200 +
{
201 +
    auto* translator = getTranslator(trans, nullptr);
202 +
    if (translator == nullptr) {
203 +
        return HELICS_FALSE;
204 +
    }
205 +
    return (translator->isValid()) ? HELICS_TRUE : HELICS_FALSE;
206 +
}
207 +
208 +
/** get the name of the translator*/
209 +
const char* helicsTranslatorGetName(HelicsTranslator trans)
210 +
{
211 +
    auto* translator = getTranslator(trans, nullptr);
212 +
    if (translator == nullptr) {
213 +
        return gEmptyStr.c_str();
214 +
    }
215 +
    const auto& name = translator->getName();
216 +
    return name.c_str();
217 +
}
218 +
219 +
void helicsTranslatorSet(HelicsTranslator trans, const char* prop, double val, HelicsError* err)
220 +
{
221 +
    auto* translator = getTranslator(trans, err);
222 +
    if (translator == nullptr) {
223 +
        return;
224 +
    }
225 +
    CHECK_NULL_STRING(prop, void());
226 +
    try {
227 +
        translator->set(prop, val);
228 +
    }
229 +
    catch (...) {
230 +
        helicsErrorHandler(err);
231 +
    }
232 +
}
233 +
234 +
void helicsTranslatorSetString(HelicsTranslator trans, const char* prop, const char* val, HelicsError* err)
235 +
{
236 +
    auto* translator = getTranslator(trans, err);
237 +
    if (translator == nullptr) {
238 +
        return;
239 +
    }
240 +
    CHECK_NULL_STRING(prop, void());
241 +
    try {
242 +
        translator->setString(prop, val);
243 +
    }
244 +
    catch (...) {
245 +
        helicsErrorHandler(err);
246 +
    }
247 +
}
248 +
249 +
void helicsTranslatorAddInputTarget(HelicsTranslator trans, const char* inp, HelicsError* err)
250 +
{
251 +
    auto* translator = getTranslator(trans, err);
252 +
    if (translator == nullptr) {
253 +
        return;
254 +
    }
255 +
    CHECK_NULL_STRING(inp, void());
256 +
    try {
257 +
        translator->addInputTarget(inp);
258 +
    }
259 +
    // LCOV_EXCL_START
260 +
    catch (...) {
261 +
        helicsErrorHandler(err);
262 +
    }
263 +
    // LCOV_EXCL_STOP
264 +
}
265 +
266 +
void helicsTranslatorAddPublicationTarget(HelicsTranslator trans, const char* pub, HelicsError* err)
267 +
{
268 +
    auto* translator = getTranslator(trans, err);
269 +
    if (translator == nullptr) {
270 +
        return;
271 +
    }
272 +
    CHECK_NULL_STRING(pub, void());
273 +
    try {
274 +
        translator->addPublication(pub);
275 +
    }
276 +
    // LCOV_EXCL_START
277 +
    catch (...) {
278 +
        helicsErrorHandler(err);
279 +
    }
280 +
    // LCOV_EXCL_STOP
281 +
}
282 +
283 +
void helicsTranslatorAddDestinationEndpoint(HelicsTranslator trans, const char* ept, HelicsError* err)
284 +
{
285 +
    auto* translator = getTranslator(trans, err);
286 +
    if (translator == nullptr) {
287 +
        return;
288 +
    }
289 +
    CHECK_NULL_STRING(ept, void());
290 +
    try {
291 +
        translator->addDestinationEndpoint(ept);
292 +
    }
293 +
    // LCOV_EXCL_START
294 +
    catch (...) {
295 +
        helicsErrorHandler(err);
296 +
    }
297 +
    // LCOV_EXCL_STOP
298 +
}
299 +
300 +
void helicsTranslatorAddSourceEndpoint(HelicsTranslator trans, const char* ept, HelicsError* err)
301 +
{
302 +
    auto* translator = getTranslator(trans, err);
303 +
    if (translator == nullptr) {
304 +
        return;
305 +
    }
306 +
    CHECK_NULL_STRING(ept, void());
307 +
    try {
308 +
        translator->addSourceEndpoint(ept);
309 +
    }
310 +
    // LCOV_EXCL_START
311 +
    catch (...) {
312 +
        helicsErrorHandler(err);
313 +
    }
314 +
    // LCOV_EXCL_STOP
315 +
}
316 +
317 +
void helicsTranslatorRemoveTarget(HelicsTranslator trans, const char* target, HelicsError* err)
318 +
{
319 +
    auto* translator = getTranslator(trans, err);
320 +
    if (translator == nullptr) {
321 +
        return;
322 +
    }
323 +
    CHECK_NULL_STRING(target, void());
324 +
    try {
325 +
        translator->removeTarget(target);
326 +
    }
327 +
    // LCOV_EXCL_START
328 +
    catch (...) {
329 +
        helicsErrorHandler(err);
330 +
    }
331 +
    // LCOV_EXCL_STOP
332 +
}
333 +
334 +
const char* helicsTranslatorGetInfo(HelicsTranslator trans)
335 +
{
336 +
    auto* transObj = getTranslatorObj(trans, nullptr);
337 +
    if (transObj == nullptr) {
338 +
        return gEmptyStr.c_str();
339 +
    }
340 +
    try {
341 +
        const std::string& info = transObj->transPtr->getInfo();
342 +
        return info.c_str();
343 +
    }
344 +
    // LCOV_EXCL_START
345 +
    catch (...) {
346 +
        return gEmptyStr.c_str();
347 +
    }
348 +
    // LCOV_EXCL_STOP
349 +
}
350 +
351 +
void helicsTranslatorSetInfo(HelicsTranslator trans, const char* info, HelicsError* err)
352 +
{
353 +
    auto* transObj = getTranslatorObj(trans, err);
354 +
    if (transObj == nullptr) {
355 +
        return;
356 +
    }
357 +
    try {
358 +
        transObj->transPtr->setInfo(AS_STRING(info));
359 +
    }
360 +
    // LCOV_EXCL_START
361 +
    catch (...) {
362 +
        helicsErrorHandler(err);
363 +
    }
364 +
    // LCOV_EXCL_STOP
365 +
}
366 +
367 +
const char* helicsTranslatorGetTag(HelicsTranslator trans, const char* tagname)
368 +
{
369 +
    auto* transObj = getTranslatorObj(trans, nullptr);
370 +
    if (transObj == nullptr) {
371 +
        return gEmptyStr.c_str();
372 +
    }
373 +
    try {
374 +
        const std::string& info = transObj->transPtr->getTag(AS_STRING(tagname));
375 +
        return info.c_str();
376 +
    }
377 +
    // LCOV_EXCL_START
378 +
    catch (...) {
379 +
        return gEmptyStr.c_str();
380 +
    }
381 +
    // LCOV_EXCL_STOP
382 +
}
383 +
384 +
void helicsTranslatorSetTag(HelicsTranslator trans, const char* tagname, const char* tagvalue, HelicsError* err)
385 +
{
386 +
    auto* transObj = getTranslatorObj(trans, err);
387 +
    if (transObj == nullptr) {
388 +
        return;
389 +
    }
390 +
    try {
391 +
        transObj->transPtr->setTag(AS_STRING(tagname), AS_STRING(tagvalue));
392 +
    }
393 +
    // LCOV_EXCL_START
394 +
    catch (...) {
395 +
        helicsErrorHandler(err);
396 +
    }
397 +
    // LCOV_EXCL_STOP
398 +
}
399 +
400 +
void helicsTranslatorSetOption(HelicsTranslator trans, int option, int value, HelicsError* err)
401 +
{
402 +
    auto* transObj = getTranslatorObj(trans, err);
403 +
    if (transObj == nullptr) {
404 +
        return;
405 +
    }
406 +
    try {
407 +
        transObj->transPtr->setOption(option, value);
408 +
    }
409 +
    // LCOV_EXCL_START
410 +
    catch (...) {
411 +
        helicsErrorHandler(err);
412 +
    }
413 +
    // LCOV_EXCL_STOP
414 +
}
415 +
416 +
int helicsTranslatorGetOption(HelicsTranslator trans, int option)
417 +
{
418 +
    auto* transObj = getTranslatorObj(trans, nullptr);
419 +
    if (transObj == nullptr) {
420 +
        return HELICS_FALSE;
421 +
    }
422 +
    try {
423 +
        return transObj->transPtr->getOption(option);
424 +
    }
425 +
    // LCOV_EXCL_START
426 +
    catch (...) {
427 +
        return HELICS_FALSE;
428 +
    }
429 +
    // LCOV_EXCL_STOP
430 +
}
431 +
432 +
void helicsTranslatorSetCustomCallbacks(HelicsTranslator trans,
433 +
                                        void (* /*toValueCall*/)(HelicsMessage message, HelicsDataBuffer out, void* userData),
434 +
                                        void (* /*toMessageCall*/)(HelicsDataBuffer value, HelicsMessage out, void* userData),
435 +
                                        void* /*userdata*/,
436 +
                                        HelicsError* err)
437 +
{
438 +
    auto* fObj = getTranslatorObj(trans, err);
439 +
    if (fObj == nullptr || fObj->transPtr == nullptr) {
440 +
        return;
441 +
    }
442 +
443 +
    if (!fObj->custom) {
444 +
        static constexpr char nonCustomTranslatorString[] = "Translator must be a custom Translator to specify callback";
445 +
        assignError(err, HELICS_ERROR_INVALID_OBJECT, nonCustomTranslatorString);
446 +
        return;
447 +
    }
448 +
    auto op = std::make_shared<helics::CustomTranslatorOperator>();
449 +
450 +
    try {
451 +
        fObj->transPtr->setOperator(std::move(op));
452 +
    }
453 +
    catch (...) {  // LCOV_EXCL_LINE
454 +
        helicsErrorHandler(err);  // LCOV_EXCL_LINE
455 +
    }
456 +
}

@@ -135,12 +135,12 @@
Loading
135 135
    return inp;
136 136
}
137 137
138 -
void ValueFederate::addTarget(const Publication& pub, const std::string& target)
138 +
void ValueFederate::addTarget(const Publication& pub, std::string_view target)
139 139
{
140 140
    vfManager->addTarget(pub, target);
141 141
}
142 142
143 -
void ValueFederate::addTarget(const Input& inp, const std::string& target)
143 +
void ValueFederate::addTarget(const Input& inp, std::string_view target)
144 144
{
145 145
    vfManager->addTarget(inp, target);
146 146
}
@@ -149,12 +149,12 @@
Loading
149 149
{
150 150
    vfManager->addAlias(inp, shortcutName);
151 151
}
152 -
void ValueFederate::removeTarget(const Publication& pub, const std::string& target)
152 +
void ValueFederate::removeTarget(const Publication& pub, std::string_view target)
153 153
{
154 154
    vfManager->removeTarget(pub, target);
155 155
}
156 156
157 -
void ValueFederate::removeTarget(const Input& inp, const std::string& target)
157 +
void ValueFederate::removeTarget(const Input& inp, std::string_view target)
158 158
{
159 159
    vfManager->removeTarget(inp, target);
160 160
}
@@ -264,14 +264,22 @@
Loading
264 264
    if (doc.isMember("subscriptions")) {
265 265
        auto subs = doc["subscriptions"];
266 266
        for (const auto& sub : subs) {
267 +
            bool skipNameTarget{false};
267 268
            auto name = fileops::getName(sub);
269 +
            if (name.empty()) {
270 +
                fileops::replaceIfMember(sub, "target", name);
271 +
                skipNameTarget = true;
272 +
            }
268 273
            auto* subAct = &vfManager->getSubscription(name);
269 274
            if (!subAct->isValid()) {
270 275
                auto type = fileops::getOrDefault(sub, "type", emptyStr);
271 276
                auto units = fileops::getOrDefault(sub, "unit", emptyStr);
272 277
                fileops::replaceIfMember(sub, "units", units);
273 278
                subAct = &registerInput(emptyStr, type, units);
274 -
                subAct->addTarget(name);
279 +
                if (!skipNameTarget) {
280 +
                    // this check is to prevent some warnings since targets get added later
281 +
                    subAct->addTarget(name);
282 +
                }
275 283
            }
276 284
            loadOptions(this, sub, *subAct);
277 285
        }
@@ -350,6 +358,11 @@
Loading
350 358
        auto& subArray = subs.as_array();
351 359
        for (const auto& sub : subArray) {
352 360
            auto name = fileops::getName(sub);
361 +
            bool skipNameTarget{false};
362 +
            if (name.empty()) {
363 +
                fileops::replaceIfMember(sub, "target", name);
364 +
                skipNameTarget = true;
365 +
            }
353 366
            Input* id = &vfManager->getSubscription(name);
354 367
            if (!id->isValid()) {
355 368
                auto type = getOrDefault(sub, "type", emptyStr);
@@ -357,7 +370,10 @@
Loading
357 370
                replaceIfMember(sub, "units", units);
358 371
359 372
                id = &registerInput(emptyStr, type, units);
360 -
                id->addTarget(name);
373 +
                if (!skipNameTarget) {
374 +
                    // this check is to prevent some warnings since targets get added later
375 +
                    id->addTarget(name);
376 +
                }
361 377
            }
362 378
363 379
            loadOptions(this, sub, *id);

@@ -0,0 +1,61 @@
Loading
1 +
/*
2 +
Copyright (c) 2017-2022,
3 +
Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable
4 +
Energy, LLC.  See the top-level NOTICE for additional details. All rights reserved.
5 +
SPDX-License-Identifier: BSD-3-Clause
6 +
*/
7 +
#pragma once
8 +
9 +
#include "EndpointInfo.hpp"
10 +
#include "InputInfo.hpp"
11 +
#include "PublicationInfo.hpp"
12 +
#include "basic_CoreTypes.hpp"
13 +
14 +
#include <memory>
15 +
#include <string>
16 +
#include <utility>
17 +
#include <vector>
18 +
19 +
namespace helics {
20 +
struct TransInformation {
21 +
    GlobalHandle id;
22 +
    std::string key;
23 +
    std::string type;
24 +
    TransInformation() = default;
25 +
    TransInformation(GlobalHandle gid, std::string_view key_, std::string_view type_):
26 +
        id(gid), key(key_), type(type_)
27 +
    {
28 +
    }
29 +
};
30 +
31 +
/** data class defining the information about a translator*/
32 +
class TranslatorInfo {
33 +
  public:
34 +
    /** constructor from all fields*/
35 +
    TranslatorInfo(GlobalHandle handle,
36 +
                   std::string_view key_,
37 +
                   std::string_view endpointType,
38 +
                   std::string_view units):
39 +
        id(handle),
40 +
        key(key_), pub(handle, key_, "any", units), ipt(handle, key_, "any", units),
41 +
        ept(handle, key_, endpointType)
42 +
    {
43 +
    }
44 +
    const GlobalHandle id;  //!< id of the translator
45 +
46 +
    const std::string key;  //!< the identifier of the translator
47 +
    uint16_t flags = 0;  //!< flags for the translator
48 +
    // there is a 4 byte gap here
49 +
    std::shared_ptr<TranslatorOperator> tranOp;  //!< the callback operation of the translator
50 +
51 +
  private:
52 +
    PublicationInfo pub;  //!< translator publication interface
53 +
    InputInfo ipt;  //!< translator input interface
54 +
    EndpointInfo ept;  //!< translator endpoint interface
55 +
56 +
  public:
57 +
    PublicationInfo* getPubInfo() { return &pub; }
58 +
    InputInfo* getInputInfo() { return &ipt; }
59 +
    EndpointInfo* getEndpointInfo() { return &ept; }
60 +
};
61 +
}  // namespace helics

@@ -29,8 +29,8 @@
Loading
29 29
                               core->getIdentifier(),
30 30
                               message);
31 31
            core->sendErrorToFederates(-5, message);
32 -
            core->processDisconnect();
33 32
            core->brokerState = BrokerBase::BrokerState::errored;
33 +
            core->sendDisconnect();
34 34
            core->addActionMessage(CMD_STOP);
35 35
        } else {  // ping again
36 36
            ActionMessage png(CMD_PING_PRIORITY);
@@ -101,7 +101,7 @@
Loading
101 101
                              brk->getIdentifier(),
102 102
                              "broker lost connection with parent");
103 103
            brk->sendErrorToImmediateBrokers(-5);
104 -
            brk->processDisconnect();
104 +
            brk->sendDisconnect(CMD_GLOBAL_DISCONNECT);
105 105
            brk->brokerState = BrokerBase::BrokerState::errored;
106 106
            brk->addActionMessage(CMD_STOP);
107 107
        } else {  // ping again

@@ -333,7 +333,7 @@
Loading
333 333
    void FindandNotifyFilterTargets(BasicHandleInfo& handleInfo);
334 334
    void FindandNotifyEndpointTargets(BasicHandleInfo& handleInfo);
335 335
    /** process a disconnect message*/
336 -
    void processDisconnect(ActionMessage& command);
336 +
    void processDisconnectCommand(ActionMessage& command);
337 337
    /** process an error message*/
338 338
    void processError(ActionMessage& command);
339 339
    /** disconnect a broker/core*/
@@ -382,6 +382,7 @@
Loading
382 382
    void addInput(ActionMessage& m);
383 383
    void addEndpoint(ActionMessage& m);
384 384
    void addFilter(ActionMessage& m);
385 +
    void addTranslator(ActionMessage& m);
385 386
    // Handle the registration of new brokers
386 387
    void brokerRegistration(ActionMessage&& command);
387 388
    // Helper function for linking interfaces
@@ -397,7 +398,6 @@
Loading
397 398
                              bool force_ordering);
398 399
399 400
    std::string generateGlobalStatus(fileops::JsonMapBuilder& builder);
400 -
401 401
    /** send an error code to all direct cores*/
402 402
    void sendErrorToImmediateBrokers(int errorCode);
403 403
    /** send a disconnect message to time dependencies and child brokers*/

@@ -35,6 +35,18 @@
Loading
35 35
    disconnect();
36 36
}
37 37
38 +
/** load network information into the comms object*/
39 +
void TcpCommsSS::loadNetworkInfo(const NetworkBrokerData& netInfo)
40 +
{
41 +
    NetworkCommsInterface::loadNetworkInfo(netInfo);
42 +
    if (!propertyLock()) {
43 +
        return;
44 +
    }
45 +
    reuse_address = netInfo.reuse_address;
46 +
    encryption_config = netInfo.encryptionConfig;
47 +
    propertyUnLock();
48 +
}
49 +
38 50
int TcpCommsSS::getDefaultBrokerPort() const
39 51
{
40 52
    return getDefaultPort(HELICS_CORE_TYPE_TCP_SS);
@@ -73,6 +85,11 @@
Loading
73 85
            outgoingConnectionsAllowed = val;
74 86
            propertyUnLock();
75 87
        }
88 +
    } else if (flag == "encrypted") {
89 +
        if (propertyLock()) {
90 +
            encrypted = val;
91 +
            propertyUnLock();
92 +
        }
76 93
    } else {
77 94
        NetworkCommsInterface::setFlag(flag, val);
78 95
    }
@@ -134,6 +151,8 @@
Loading
134 151
    }
135 152
    gmlc::networking::TcpServer::pointer server;
136 153
    auto ioctx = gmlc::networking::AsioContextManager::getContextPointer();
154 +
    auto sf = encrypted ? gmlc::networking::SocketFactory(encryption_config) :
155 +
                          gmlc::networking::SocketFactory();
137 156
    auto contextLoop = ioctx->startContextLoop();
138 157
    auto dataCall =
139 158
        [this](const TcpConnection::pointer& connection, const char* data, size_t datasize) {
@@ -145,7 +164,8 @@
Loading
145 164
    };
146 165
147 166
    if (serverMode) {
148 -
        server = gmlc::networking::TcpServer::create(ioctx->getBaseContext(),
167 +
        server = gmlc::networking::TcpServer::create(sf,
168 +
                                                     ioctx->getBaseContext(),
149 169
                                                     localTargetAddress,
150 170
                                                     static_cast<uint16_t>(PortNumber.load()),
151 171
                                                     true,
@@ -177,15 +197,22 @@
Loading
177 197
    std::map<std::string, route_id> established_routes;
178 198
    if (outgoingConnectionsAllowed) {
179 199
        for (const auto& conn : connections) {
180 -
            auto new_connect = gmlc::networking::establishConnection(ioctx->getBaseContext(), conn);
200 +
            try {
201 +
                auto new_connect =
202 +
                    gmlc::networking::establishConnection(sf, ioctx->getBaseContext(), conn);
181 203
182 -
            if (new_connect) {
183 -
                new_connect->setDataCall(dataCall);
184 -
                new_connect->setErrorCall(errorCall);
185 -
                new_connect->send(cstring);
186 -
                new_connect->startReceive();
204 +
                if (new_connect) {
205 +
                    new_connect->setDataCall(dataCall);
206 +
                    new_connect->setErrorCall(errorCall);
207 +
                    new_connect->send(cstring);
208 +
                    new_connect->startReceive();
187 209
188 -
                made_connections.emplace_back(conn, std::move(new_connect));
210 +
                    made_connections.emplace_back(conn, std::move(new_connect));
211 +
                }
212 +
            }
213 +
            catch (const std::exception& e) {
214 +
                logWarning(std::string("unable to establish connection with ") + conn +
215 +
                           "::" + e.what());
189 216
            }
190 217
        }
191 218
    }
@@ -204,7 +231,8 @@
Loading
204 231
        }
205 232
        if (outgoingConnectionsAllowed) {
206 233
            try {
207 -
                brokerConnection = gmlc::networking::establishConnection(ioctx->getBaseContext(),
234 +
                brokerConnection = gmlc::networking::establishConnection(sf,
235 +
                                                                         ioctx->getBaseContext(),
208 236
                                                                         brokerTargetAddress,
209 237
                                                                         std::to_string(brokerPort),
210 238
                                                                         std::chrono::milliseconds(
@@ -227,7 +255,8 @@
Loading
227 255
                brokerConnection->startReceive();
228 256
            }
229 257
            catch (std::exception& e) {
230 -
                logError(e.what());
258 +
                logError(std::string("unable to establish connection with ") + brokerTargetAddress +
259 +
                         "::" + e.what());
231 260
                setTxStatus(connection_status::error);
232 261
                setRxStatus(connection_status::error);
233 262
                return;
@@ -299,20 +328,29 @@
Loading
299 328
300 329
                        if (!established) {
301 330
                            if (outgoingConnectionsAllowed) {
302 -
                                auto new_connect = gmlc::networking::establishConnection(
303 -
                                    ioctx->getBaseContext(), std::string(cmd.payload.to_string()));
304 -
                                if (new_connect) {
305 -
                                    new_connect->setDataCall(dataCall);
306 -
                                    new_connect->setErrorCall(errorCall);
307 -
                                    new_connect->send(cstring);
308 -
                                    new_connect->startReceive();
309 -
                                    routes.emplace(route_id{cmd.getExtraData()},
310 -
                                                   std::move(new_connect));
311 -
                                    established_routes[std::string(cmd.payload.to_string())] =
312 -
                                        route_id{cmd.getExtraData()};
331 +
                                try {
332 +
                                    auto new_connect = gmlc::networking::establishConnection(
333 +
                                        sf,
334 +
                                        ioctx->getBaseContext(),
335 +
                                        std::string(cmd.payload.to_string()));
336 +
                                    if (new_connect) {
337 +
                                        new_connect->setDataCall(dataCall);
338 +
                                        new_connect->setErrorCall(errorCall);
339 +
                                        new_connect->send(cstring);
340 +
                                        new_connect->startReceive();
341 +
                                        routes.emplace(route_id{cmd.getExtraData()},
342 +
                                                       std::move(new_connect));
343 +
                                        established_routes[std::string(cmd.payload.to_string())] =
344 +
                                            route_id{cmd.getExtraData()};
345 +
                                    }
346 +
                                }
347 +
                                catch (const std::exception& e) {
348 +
                                    logWarning(std::string("unable to establish connection with ") +
349 +
                                               std::string(cmd.payload.to_string()) +
350 +
                                               "::" + e.what());
313 351
                                }
314 352
                            } else {
315 -
                                logWarning(std::string("unable to make connection ") +
353 +
                                logWarning(std::string("outgoing connections not allowed ") +
316 354
                                           std::string(cmd.payload.to_string()));
317 355
                            }
318 356
                        }

@@ -29,12 +29,13 @@
Loading
29 29
    otherwise we would need two classes that do basically the same thing just with different
30 30
    container types so using deque reduce the amount of the code to maintain as well*/
31 31
    std::deque<BasicHandleInfo> handles;  //!< local handle information
32 -
    std::unordered_map<std::string_view, InterfaceHandle>
33 -
        publications;  //!< map of all local publications
34 -
    std::unordered_map<std::string_view, InterfaceHandle>
35 -
        endpoints;  //!< map of all local endpoints
32 +
    /// map of all local publications
33 +
    std::unordered_map<std::string_view, InterfaceHandle> publications;
34 +
    /// map of all local endpoints
35 +
    std::unordered_map<std::string_view, InterfaceHandle> endpoints;
36 36
    std::unordered_map<std::string_view, InterfaceHandle> inputs;  //!< map of all local endpoints
37 37
    std::unordered_map<std::string_view, InterfaceHandle> filters;  //!< map of all local endpoints
38 +
    std::unordered_map<std::string_view, InterfaceHandle> translators;  //!< map of all translators
38 39
    std::unordered_map<std::uint64_t, int32_t> unique_ids;  //!< map of identifiers
39 40
  public:
40 41
    /** default constructor*/
@@ -42,16 +43,16 @@
Loading
42 43
    /** add a handle to manage*/
43 44
    BasicHandleInfo& addHandle(GlobalFederateId fed_id,
44 45
                               InterfaceType what,
45 -
                               const std::string& key,
46 -
                               const std::string& type,
47 -
                               const std::string& units);
46 +
                               std::string_view key,
47 +
                               std::string_view type,
48 +
                               std::string_view units);
48 49
    /** add a handle to manage*/
49 50
    BasicHandleInfo& addHandle(GlobalFederateId fed_id,
50 51
                               InterfaceHandle local_id,
51 52
                               InterfaceType what,
52 -
                               const std::string& key,
53 -
                               const std::string& type,
54 -
                               const std::string& units);
53 +
                               std::string_view key,
54 +
                               std::string_view type,
55 +
                               std::string_view units);
55 56
56 57
    void addHandle(const BasicHandleInfo& otherHandle);
57 58
    /** add a handle at the specified index*/
@@ -87,10 +88,17 @@
Loading
87 88
    /** get a const filter by name*/
88 89
    const BasicHandleInfo* getFilter(std::string_view name) const;
89 90
    BasicHandleInfo* getFilter(std::string_view name);
90 -
    // auto getFilters (const std::string &name) const { return filters.equal_range (name); }
91 91
    /** get a filter by index
92 92
    @return nullptr if the index doesn't point to a valid filter*/
93 93
    BasicHandleInfo* getFilter(InterfaceHandle handle);
94 +
95 +
    const BasicHandleInfo* getTranslator(std::string_view name) const;
96 +
    BasicHandleInfo* getTranslator(std::string_view name);
97 +
    /** get a translator by index
98 +
    @return nullptr if the index doesn't point to a valid translator*/
99 +
    BasicHandleInfo* getTranslator(InterfaceHandle handle);
100 +
101 +
    /** get a publication by name*/
94 102
    BasicHandleInfo* getPublication(std::string_view name);
95 103
    const BasicHandleInfo* getPublication(std::string_view name) const;
96 104
    /** get a publication by index

@@ -72,7 +72,10 @@
Loading
72 72
    }
73 73
#endif
74 74
    /** destructor*/
75 -
    ~FederateInfo() { helicsFederateInfoFree(fi); }
75 +
    ~FederateInfo()
76 +
    {
77 +
        helicsFederateInfoFree(fi);
78 +
    }
76 79
    void loadFromArgs(const std::string& argString)
77 80
    {
78 81
        helicsFederateInfoLoadFromString(fi, argString.c_str(), HELICS_NULL_POINTER);
@@ -84,7 +87,10 @@
Loading
84 87
        helicsFederateInfoSetCoreName(fi, corename.c_str(), HELICS_NULL_POINTER);
85 88
    }
86 89
    /// Set the separator character
87 -
    void setSeparator(char sep) { helicsFederateInfoSetSeparator(fi, sep, HELICS_NULL_POINTER); }
90 +
    void setSeparator(char sep)
91 +
    {
92 +
        helicsFederateInfoSetSeparator(fi, sep, HELICS_NULL_POINTER);
93 +
    }
88 94
    /** set the core init string to use in the federateInfo
89 95
    @param coreInit the core name to use*/
90 96
    void setCoreInit(const std::string& coreInit)
@@ -159,14 +165,20 @@
Loading
159 165
        helicsFederateSendCommand(fi, target.c_str(), cmd.c_str(), HELICS_IGNORE_ERROR);
160 166
    }
161 167
162 -
    const char* getCommand() { return helicsFederateGetCommand(fi, HELICS_IGNORE_ERROR); }
168 +
    const char* getCommand()
169 +
    {
170 +
        return helicsFederateGetCommand(fi, HELICS_IGNORE_ERROR);
171 +
    }
163 172
164 173
    const char* getCommandSource()
165 174
    {
166 175
        return helicsFederateGetCommandSource(fi, HELICS_IGNORE_ERROR);
167 176
    }
168 177
    /** get the underlying HelicsFederateInfo object*/
169 -
    HelicsFederateInfo getInfo() { return fi; }
178 +
    HelicsFederateInfo getInfo()
179 +
    {
180 +
        return fi;
181 +
    }
170 182
171 183
  private:
172 184
    HelicsFederateInfo fi;  //!< handle for the underlying federate_info object
@@ -193,6 +205,35 @@
Loading
193 205
        auto cback = reinterpret_cast<std::function<void(HelicsTime, bool)>*>(userData);
194 206
        (*cback)(time, iterating == HELICS_TRUE);
195 207
    }
208 +
209 +
    /** helper function for the callback executor for state change*/
210 +
    inline void helicCppStateChangeCallbackExecutor(HelicsFederateState newState,
211 +
                                                    HelicsFederateState oldState,
212 +
                                                    void* userData)
213 +
    {
214 +
        auto cback =
215 +
            reinterpret_cast<std::function<void(HelicsFederateState, HelicsFederateState)>*>(
216 +
                userData);
217 +
        (*cback)(newState, oldState);
218 +
    }
219 +
220 +
    /** helper function for the callback executor for time request entry*/
221 +
    inline void helicCppTimeRequestEntryCallbackExecutor(HelicsTime currentTime,
222 +
                                                         HelicsTime requestTime,
223 +
                                                         HelicsBool iterating,
224 +
                                                         void* userData)
225 +
    {
226 +
        auto cback = reinterpret_cast<std::function<void(HelicsTime, HelicsTime, bool)>*>(userData);
227 +
        (*cback)(currentTime, requestTime, iterating == HELICS_TRUE);
228 +
    }
229 +
    /** helper function for the callback executor for time request return*/
230 +
    inline void helicCppTimeRequestReturnCallbackExecutor(HelicsTime newTime,
231 +
                                                          HelicsBool iterating,
232 +
                                                          void* userData)
233 +
    {
234 +
        auto cback = reinterpret_cast<std::function<void(HelicsTime, bool)>*>(userData);
235 +
        (*cback)(newTime, iterating == HELICS_TRUE);
236 +
    }
196 237
}  // namespace details
197 238
#endif
198 239
@@ -221,9 +262,10 @@
Loading
221 262
    }
222 263
#ifdef HELICS_HAS_RVALUE_REFS
223 264
    /** move constructor*/
224 -
    Federate(Federate&& fedObj) HELICS_NOTHROW: exec_async_iterate(fedObj.exec_async_iterate)
265 +
    Federate(Federate&& fedObj) HELICS_NOTHROW:
266 +
        fed(fedObj.fed),
267 +
        exec_async_iterate(fedObj.exec_async_iterate)
225 268
    {
226 -
        fed = fedObj.fed;
227 269
        fedObj.fed = HELICS_NULL_POINTER;
228 270
    }
229 271
    /** move assignment operator*/
@@ -242,22 +284,19 @@
Loading
242 284
            helicsFederateFree(fed);
243 285
        }
244 286
#if defined(HELICS_HAS_FUNCTIONAL) && HELICS_HAS_FUNCTIONAL != 0
245 -
        if (callbackBuffer != nullptr) {
246 -
            auto cback =
247 -
                reinterpret_cast<std::function<std::string(const std::string&)>*>(callbackBuffer);
248 -
            delete cback;
249 -
        }
250 -
        if (timeUpdateCallbackBuffer != nullptr) {
251 -
            auto cback =
252 -
                reinterpret_cast<std::function<void(HelicsTime, bool)>*>(timeUpdateCallbackBuffer);
253 -
            delete cback;
254 -
        }
287 +
        freeCallbacks();
255 288
#endif
256 289
    }
257 290
    /** cast operator to get the underlying HelicsFederate object*/
258 -
    operator HelicsFederate() const { return fed; }
291 +
    operator HelicsFederate() const
292 +
    {
293 +
        return fed;
294 +
    }
259 295
    /** get the underlying HelicsFederate object*/
260 -
    HelicsFederate baseObject() const { return fed; }
296 +
    HelicsFederate baseObject() const
297 +
    {
298 +
        return fed;
299 +
    }
261 300
    /** set a flag for the federate
262 301
   @param flag an index into the flag /ref flag-definitions.h
263 302
   @param flagValue the value of the flag defaults to true
@@ -314,7 +353,10 @@
Loading
314 353
    and should be called before any local interfaces are created otherwise it may not be possible to
315 354
    retrieve them without using the full name.  recommended possibilities are ('.','/', ':','-','_')
316 355
     */
317 -
    void setSeparator(char sep) { helicsFederateSetSeparator(fed, sep, HELICS_NULL_POINTER); }
356 +
    void setSeparator(char sep)
357 +
    {
358 +
        helicsFederateSetSeparator(fed, sep, HELICS_NULL_POINTER);
359 +
    }
318 360
    /** register a set of interfaces defined in a file
319 361
    @details call is only valid in startup mode
320 362
    @param configString  the location of the file or config String to load to generate the
@@ -332,7 +374,10 @@
Loading
332 374
    /** enter the initialization mode after all interfaces have been defined
333 375
    @details  the call will block until all federates have entered initialization mode
334 376
    */
335 -
    void enterInitializingMode() { helicsFederateEnterInitializingMode(fed, hThrowOnError()); }
377 +
    void enterInitializingMode()
378 +
    {
379 +
        helicsFederateEnterInitializingMode(fed, hThrowOnError());
380 +
    }
336 381
    /** enter the initialization mode after all interfaces have been defined
337 382
   @details  the call will not block but a call to \ref enterInitializingModeComplete should be made
338 383
   to complete the call sequence
@@ -406,14 +451,26 @@
Loading
406 451
    /** terminate the simulation
407 452
   @details call is will block until the finalize has been acknowledged, no commands that interact
408 453
   with the core may be called after this function function */
409 -
    void finalize() { helicsFederateFinalize(fed, hThrowOnError()); }
454 +
    void finalize()
455 +
    {
456 +
        helicsFederateFinalize(fed, hThrowOnError());
457 +
    }
410 458
    /** terminate the simulation in a non-blocking call
411 459
    @details finalizeComplete must be called after this call to complete the finalize procedure*/
412 -
    void finalizeAsync() { helicsFederateFinalizeAsync(fed, hThrowOnError()); }
460 +
    void finalizeAsync()
461 +
    {
462 +
        helicsFederateFinalizeAsync(fed, hThrowOnError());
463 +
    }
413 464
    /** complete the asynchronous terminate pair*/
414 -
    void finalizeComplete() { helicsFederateFinalizeComplete(fed, hThrowOnError()); }
465 +
    void finalizeComplete()
466 +
    {
467 +
        helicsFederateFinalizeComplete(fed, hThrowOnError());
468 +
    }
415 469
    /** get the current time from a federate */
416 -
    HelicsTime getCurrentTime() { return helicsFederateGetCurrentTime(fed, hThrowOnError()); }
470 +
    HelicsTime getCurrentTime()
471 +
    {
472 +
        return helicsFederateGetCurrentTime(fed, hThrowOnError());
473 +
    }
417 474
    /** request a time advancement
418 475
   @param time the next requested time step
419 476
   @return the granted time step*/
@@ -423,7 +480,10 @@
Loading
423 480
    }
424 481
    /** request a time advancement to the next allowed time
425 482
    @return the granted time step*/
426 -
    HelicsTime requestNextStep() { return helicsFederateRequestNextStep(fed, hThrowOnError()); }
483 +
    HelicsTime requestNextStep()
484 +
    {
485 +
        return helicsFederateRequestNextStep(fed, hThrowOnError());
486 +
    }
427 487
428 488
    /** request a time advancement to the next allowed time
429 489
    @param timeDelta the amount of time requested to advance
@@ -486,7 +546,10 @@
Loading
486 546
        helicsFederateProcessCommunications(fed, period, HELICS_IGNORE_ERROR);
487 547
    }
488 548
    /** get the federate name*/
489 -
    const char* getName() const { return helicsFederateGetName(fed); }
549 +
    const char* getName() const
550 +
    {
551 +
        return helicsFederateGetName(fed);
552 +
    }
490 553
491 554
    /** make a query of the federate
492 555
    @details this call is blocking until the value is returned which make take some time depending
@@ -548,6 +611,17 @@
Loading
548 611
    {
549 612
        helicsFederateSetQueryCallback(fed, queryAnswer, userdata, hThrowOnError());
550 613
    }
614 +
615 +
    void setTimeRequestEntryCallback(void (*timeRequestEntry)(HelicsTime currentTime,
616 +
                                                              HelicsTime requestTime,
617 +
                                                              HelicsBool iterating,
618 +
                                                              void* userdata),
619 +
                                     void* userdata)
620 +
621 +
    {
622 +
        helicsFederateSetTimeRequestEntryCallback(fed, timeRequestEntry, userdata, hThrowOnError());
623 +
    }
624 +
551 625
    void setTimeUpdateCallback(void (*timeUpdate)(HelicsTime time,
552 626
                                                  HelicsBool iterating,
553 627
                                                  void* userdata),
@@ -556,28 +630,92 @@
Loading
556 630
    {
557 631
        helicsFederateSetTimeUpdateCallback(fed, timeUpdate, userdata, hThrowOnError());
558 632
    }
633 +
634 +
    void setStateChangeCallback(void (*stateChange)(HelicsFederateState newState,
635 +
                                                    HelicsFederateState oldState,
636 +
                                                    void* userdata),
637 +
                                void* userdata)
638 +
639 +
    {
640 +
        helicsFederateSetStateChangeCallback(fed, stateChange, userdata, hThrowOnError());
641 +
    }
642 +
643 +
    void setTimeRequestReturnCallback(void (*timeRequestReturn)(HelicsTime newTime,
644 +
                                                                HelicsBool iterating,
645 +
                                                                void* userdata),
646 +
                                      void* userdata)
647 +
648 +
    {
649 +
        helicsFederateSetTimeRequestReturnCallback(fed,
650 +
                                                   timeRequestReturn,
651 +
                                                   userdata,
652 +
                                                   hThrowOnError());
653 +
    }
559 654
#if defined(HELICS_HAS_FUNCTIONAL) && HELICS_HAS_FUNCTIONAL != 0
560 655
    void setQueryCallback(std::function<std::string(const std::string&)> callback)
561 656
562 657
    {
563 -
        callbackBuffer = new std::function<std::string(const std::string&)>(std::move(callback));
658 +
        checkCallbackAllocation();
659 +
        callbackBuffers[queryCallbackLocation] =
660 +
            new std::function<std::string(const std::string&)>(std::move(callback));
564 661
        helicsFederateSetQueryCallback(fed,
565 662
                                       details::helicCppQueryCallbackExecutor,
566 -
                                       callbackBuffer,
663 +
                                       callbackBuffers[queryCallbackLocation],
567 664
                                       hThrowOnError());
568 665
    }
569 666
667 +
    void setTimeRequestEntryCallback(
668 +
        std::function<void(HelicsTime currentTime, HelicsTime requestTime, bool iterating)>
669 +
            callback)
670 +
671 +
    {
672 +
        checkCallbackAllocation();
673 +
        callbackBuffers[timeRequestEntryCallbackLocation] =
674 +
            new std::function<void(HelicsTime, HelicsTime, bool)>(std::move(callback));
675 +
        helicsFederateSetTimeRequestEntryCallback(fed,
676 +
                                                  details::helicCppTimeRequestEntryCallbackExecutor,
677 +
                                                  callbackBuffers[timeRequestEntryCallbackLocation],
678 +
                                                  hThrowOnError());
679 +
    }
680 +
570 681
    void setTimeUpdateCallback(std::function<void(HelicsTime time, bool iterating)> callback)
571 682
572 683
    {
573 -
        timeUpdateCallbackBuffer =
684 +
        checkCallbackAllocation();
685 +
        callbackBuffers[timeUpdateCallbackLocation] =
574 686
            new std::function<void(HelicsTime time, bool iterating)>(std::move(callback));
575 687
        helicsFederateSetTimeUpdateCallback(fed,
576 688
                                            details::helicCppTimeUpdateCallbackExecutor,
577 -
                                            timeUpdateCallbackBuffer,
689 +
                                            callbackBuffers[timeUpdateCallbackLocation],
578 690
                                            hThrowOnError());
579 691
    }
580 692
693 +
    void setStateChangeCallback(
694 +
        std::function<void(HelicsFederateState, HelicsFederateState)> callback)
695 +
696 +
    {
697 +
        checkCallbackAllocation();
698 +
        callbackBuffers[stateChangeCallbackLocation] =
699 +
            new std::function<void(HelicsFederateState, HelicsFederateState)>(std::move(callback));
700 +
        helicsFederateSetStateChangeCallback(fed,
701 +
                                             details::helicCppStateChangeCallbackExecutor,
702 +
                                             callbackBuffers[stateChangeCallbackLocation],
703 +
                                             hThrowOnError());
704 +
    }
705 +
706 +
    void setTimeRequestReturnCallback(
707 +
        std::function<void(HelicsTime newTime, bool iterating)> callback)
708 +
709 +
    {
710 +
        checkCallbackAllocation();
711 +
        callbackBuffers[timeRequestReturnCallbackLocation] =
712 +
            new std::function<void(HelicsTime, bool)>(std::move(callback));
713 +
        helicsFederateSetTimeRequestReturnCallback(
714 +
            fed,
715 +
            details::helicCppTimeRequestReturnCallbackExecutor,
716 +
            callbackBuffers[timeRequestReturnCallbackLocation],
717 +
            hThrowOnError());
718 +
    }
581 719
#endif
582 720
    /** define a filter interface
583 721
    @details a filter will modify messages coming from or going to target endpoints
@@ -624,6 +762,11 @@
Loading
624 762
                                                                       deliveryEndpoint.c_str(),
625 763
                                                                       hThrowOnError()));
626 764
    }
765 +
    /** get a count of the number of filters registered in a federate*/
766 +
    int getFilterCount() const
767 +
    {
768 +
        return helicsFederateGetFilterCount(fed);
769 +
    }
627 770
    /** get the id of a source filter from the name of the endpoint
628 771
    @param filterName the name of the filter
629 772
    @return a reference to a filter object which could be invalid if filterName is not valid*/
@@ -722,17 +865,71 @@
Loading
722 865
        helicsFederateLogLevelMessage(fed, level, message.c_str(), hThrowOnError());
723 866
    }
724 867
    /** get a Core Object*/
725 -
    HelicsCore getCore() { return helicsFederateGetCore(fed, hThrowOnError()); }
868 +
    HelicsCore getCore()
869 +
    {
870 +
        return helicsFederateGetCore(fed, hThrowOnError());
871 +
    }
726 872
    /** get the C object for use in the C library*/
727 -
    HelicsFederate getObject() const { return fed; }
873 +
    HelicsFederate getObject() const
874 +
    {
875 +
        return fed;
876 +
    }
728 877
729 878
  protected:
730 879
    HelicsFederate fed;  //!< underlying HelicsFederate object
731 880
    bool exec_async_iterate;  //!< indicator that the federate is in an async operation
732 881
#if defined(HELICS_HAS_FUNCTIONAL) && HELICS_HAS_FUNCTIONAL != 0
733 882
  private:
734 -
    void* callbackBuffer{nullptr};  //!< buffer to contain pointer to a callback
735 -
    void* timeUpdateCallbackBuffer{nullptr};  //!< buffer for pointer to time update callback
883 +
    static constexpr int numberOfCallbacks = 5;
884 +
    static constexpr int timeRequestEntryCallbackLocation = 0;
885 +
    static constexpr int timeUpdateCallbackLocation = 1;
886 +
    static constexpr int stateChangeCallbackLocation = 2;
887 +
    static constexpr int queryCallbackLocation = 3;
888 +
    static constexpr int timeRequestReturnCallbackLocation = 4;
889 +
    void** callbackBuffers{nullptr};
890 +
891 +
    void checkCallbackAllocation()
892 +
    {
893 +
        if (callbackBuffers == nullptr) {
894 +
            callbackBuffers = new void*[numberOfCallbacks];
895 +
            for (int ii = 0; ii < numberOfCallbacks; ++ii) {
896 +
                callbackBuffers[ii] = nullptr;
897 +
            }
898 +
        }
899 +
    }
900 +
    void freeCallbacks()
901 +
    {
902 +
        if (callbackBuffers == nullptr) {
903 +
            return;
904 +
        }
905 +
        if (callbackBuffers[queryCallbackLocation] != nullptr) {
906 +
            auto cback = reinterpret_cast<std::function<std::string(const std::string&)>*>(
907 +
                callbackBuffers[queryCallbackLocation]);
908 +
            delete cback;
909 +
        }
910 +
        if (callbackBuffers[timeRequestEntryCallbackLocation] != nullptr) {
911 +
            auto cback = reinterpret_cast<std::function<void(HelicsTime, HelicsTime, bool)>*>(
912 +
                callbackBuffers[timeRequestEntryCallbackLocation]);
913 +
            delete cback;
914 +
        }
915 +
        if (callbackBuffers[timeUpdateCallbackLocation] != nullptr) {
916 +
            auto cback = reinterpret_cast<std::function<void(HelicsTime, bool)>*>(
917 +
                callbackBuffers[timeUpdateCallbackLocation]);
918 +
            delete cback;
919 +
        }
920 +
        if (callbackBuffers[stateChangeCallbackLocation] != nullptr) {
921 +
            auto cback =
922 +
                reinterpret_cast<std::function<void(HelicsFederateState, HelicsFederateState)>*>(
923 +
                    callbackBuffers[stateChangeCallbackLocation]);
924 +
            delete cback;
925 +
        }
926 +
        if (callbackBuffers[timeRequestReturnCallbackLocation] != nullptr) {
927 +
            auto cback = reinterpret_cast<std::function<void(HelicsTime, bool)>*>(
928 +
                callbackBuffers[timeRequestReturnCallbackLocation]);
929 +
            delete cback;
930 +
        }
931 +
        delete[] callbackBuffers;
932 +
    }
736 933
#endif
737 934
};
738 935

@@ -18,9 +18,10 @@
Loading
18 18
#include "../core/helics_definitions.hpp"
19 19
#include "../network/loadCores.hpp"
20 20
#include "AsyncFedCallInfo.hpp"
21 +
#include "ConnectorFederateManager.hpp"
21 22
#include "CoreApp.hpp"
22 -
#include "FilterFederateManager.hpp"
23 23
#include "Filters.hpp"
24 +
#include "Translator.hpp"
24 25
#include "gmlc/utilities/stringOps.h"
25 26
#include "helics/helics-config.h"
26 27
@@ -112,7 +113,7 @@
Loading
112 113
    observerMode = fi.observer;
113 114
    currentTime = coreObject->getCurrentTime(fedID);
114 115
    asyncCallInfo = std::make_unique<shared_guarded_m<AsyncFedCallInfo>>();
115 -
    fManager = std::make_unique<FilterFederateManager>(coreObject.get(), this, fedID);
116 +
    cManager = std::make_unique<ConnectorFederateManager>(coreObject.get(), this, fedID);
116 117
}
117 118
118 119
Federate::Federate(const std::string& fedname, CoreApp& core, const FederateInfo& fi):
@@ -151,7 +152,7 @@
Loading
151 152
    strictConfigChecking = fi.checkFlagProperty(HELICS_FLAG_STRICT_CONFIG_CHECKING, true);
152 153
    currentTime = coreObject->getCurrentTime(fedID);
153 154
    asyncCallInfo = std::make_unique<shared_guarded_m<AsyncFedCallInfo>>();
154 -
    fManager = std::make_unique<FilterFederateManager>(coreObject.get(), this, fedID);
155 +
    cManager = std::make_unique<ConnectorFederateManager>(coreObject.get(), this, fedID);
155 156
}
156 157 </