c++11 – C++ generic callback implementation

I have a code that takes messages from flash player in a form of XML parse them into function and arguments and calls a registered callback for that function.
The piece of code that I want to replace is something nicely done (almost) generic Callback mechanism:
code for the generic callback implementation of flashSDK (ASInterface.inl).

The problem with it is that this code is written for flash and I want to replace the flash and use other service that will have the same interface. Is there any standard implementation of this callback mechanism (std? boost? something else open sourced?)?

This code implements generic callbacks mechanism that you can register function with number of arguments and types in a map:

void SomethingHappened(int a, int b) {print a + b;}
void SomethingElseHappened(string abcd) {print abcd;}
callbacks("SomethingHappened") = &SomethingHappened;
callbacks("SomethingElseHappened") = &SomethingElseHappened;

and than search for it and call with an array of arguments:

Callbacks::iterator itCallback = callbacks.find(functionName);
if (itCallback != callbacks.end())
{
    HRESULT result = itCallback->second.Call(arguments, returnValue);
}

full usage example:

//init callbacks
typedef std::map<std::wstring, Callback> callbacks;
void SomethingHappened(int a, int b) {print a + b;}
void SomethingElseHappened(string abcd) {print abcd;}
callbacks(functionName) = &SomethingHappened;

void MessageArrived(string xmlInput)
{
    string functionName = parseFunctionName(xmlInput);
    Callbacks::iterator itCallback = callbacks.find(functionName);
    if (itCallback != callbacks.end())
    {
        //parse arguments
        std::vector<std::wstring> args;
        _Args::split(xml, args);
        ASValue::Array arguments;
        for (size_t i = 0, s = args.size(); i < s; ++i)
        {
            ASValue arg; arg.FromXML(args(i));
            arguments.push_back(arg);
        }
        ASValue returnValue;
        //***this is where the magic happens: call the function***
        HRESULT result = itCallback->second.Call(arguments, returnValue);
        return result;
    }
}

plugins – Callback hooked to post_updated firing on new posts as well

Context: I’m using a plugin that allows me to add author boxes throughout my site (Simple Author Box), while providing an easy way for any user to update their social media links and profile pictures. I figured I could also leverage that plugin to dynamically show the team members in the site’s about section.

However, I didn’t want to have author archives for the team members that won’t be publishing any posts in the future (designer, myself etc.), so I used the solution from this question as a starting point to disable specific users’ author archives and from there I created a few additional functions in order to automate that functionality (author archives are now automatically being disabled/enabled according to the number of posts each user has published).

One of these functions is hooked to post_updated, which according to the docs: “Fires once an existing post has been updated.” (emphasis added)

Here’s the function’s code (please forgive any lack of good practices, I’m new to PHP and not an experienced programmer):

/* 
* This function does the checks and the actual value update, if needed.
* It's called from inside the callback.
*/
function maybe_update_author_archive_status($user_id, $published_posts, $author_archive_disabled) {
    if ($published_posts == 0 && $author_archive_disabled != 'on') {
        update_user_meta($user_id, '_author_archive_disabled', 'on');
    } elseif ($published_posts != 0 && $author_archive_disabled != 'off') {
        update_user_meta($user_id, '_author_archive_disabled', 'off');
    }
}

/* 
* The callback itself.
*/
function maybe_update_author_archive_status_on_post_update($post_id, $post_after, $post_before) {
    if($post_before->post_status != 'publish' && $post_after->post_status != 'publish') {
        return;
    }
    
    $old_author = $post_before->post_author;
    $new_author = $post_after->post_author;
    $authors = array($old_author);
    
    /* If the post author has changed, I might need to update both author archive status */
    if($new_author != $old_author) {
        $authors() = $new_author;
    }

    foreach($authors as $author) {
        $user_id = intval($author, 10);
        $author_archive_disabled = get_user_meta($user_id, '_author_archive_disabled', true);
        $published_posts = count_user_posts($user_id);

        maybe_update_author_archive_status($user_id, $published_posts, $author_archive_disabled);
    }
}
add_action('post_updated', 'maybe_update_author_archive_status_on_post_update', 10, 3);

However, to my surprise (and delight actually), it’s also firing when I create and publish a new post. Can anyone explain me why? Under which circumstances this function wouldn’t be fired? Even though this is the behavior I desired and everything is working as I wanted it to, this is not what I expected it would happen after reading the documentation.

the ajax callback not working with the HOOK_form_alter

I’m trying to alter a backoffice select field (field_item_permission) using an ajax callback(changePermissions),but the callback is not triggered when I change the field_referentiel_services option value :

<?php
use DrupalCoreFormFormStateInterface;

/**
 * implements hook_form_FORM_ID_alter
 * {@inheritdoc}
 */
function MYMODULE_menu_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  if($form_id == 'menu_link_content_mon-compte_form' || $form_id == 'menu_link_content_main_form'){
    // who will trigger the ajax callback ?
    $form('field_referentiel_services')('#ajax') = (
      'event' => 'change', // when the callback will be triggered ?
      'callback' => 'changePermissions',  // what to do when an event is triggered ?
      'wrapper' => 'edit-permissions', // where the callback result will be inserted ?
    );
  }

  // where the ajax callback return value will be inserted ?
  $form('field_item_permission')('#prefix') = '<div id="edit-permissions">';
  $form('field_item_permission')('#suffix') = '</div>';


}


// 3. Handle Ajax Req : the Callback function that will handle the ajax Request
//this function should return a render array that will be then converted into HTML
//and  injected in the #ajax->'wrapper' element id.
function changePermissions(array &$form,FormStateInterface $form_state) {
  // update the field_referentiel_services element select options
  $form('field_item_permission')('widget')('#options')= (
    'html_web_design' => "HTML Web Design in 7 Days",
    'html_css' => 'HTML & css',
    'html_5' => 'HTML 5'
  );
  // return the form render array that you have changed.
  return  $form('field_referentiel_services') ;
}

typescript – Problem with async/await service response with callback

I am using the node-firebird javascript module to query a firebird database.

The module responds with a callback and I can’t get the async / await working for me to wait for the response from that module.

A “padron.controller” controller makes a call to a “padron.service” service to make a query

try {
  let res = await this.padronService.getFamilia(body);
  console.log('padron.controller - Response from padron.service', res);
  return res;
} catch {
  throw new Error('Erro na DB');
}

“padron.service” call to “firebird.service” which centralizes all the query to the DB

try {
  let res = await this.firebirdService.getQuery(query, params);
  console.log('padron.service - Response from FirebirdService ================', res);
  return res;
} catch {
  throw new Error('Erro na DB');
}

El “firebird.service” uses a “node-firebird” library and and returns with a callback.

fb.attach(this.options, (err, db) => {

        if (err) throw new Error('Erro na conexión á DB');

        db.query(query, params, (err, res) => {

            if (err) throw new Error('Erro na consulta ó Padrón');;

            console.log('firebird.service - Response DB ================', res);

            db.detach();

            return res

        });

    });

My problem is the order of the answerss

padron.service - Response desde FirebirdService ================ undefined
padron.controller - Response desde padron.service undefined
firebird.service - Response DB ================ {
    USU_USUARIO: 'SUPER',
    USU_CLAVES: '',
    USU_CARGO: 'ADMINISTRADOR',
    USU_TER: null,

when the order should be

firebird.service - Respuesta DB ================ { 
    USU_USUARIO: 'SUPER',
    USU_CLAVES: '',
padron.service - Respuesta desde FirebirdService ================ undefined
padron.controller - Respuesta desde padron.service undefined

The await does not wait for the callback from the DB

And I don’t know how to fix it. Somebody can help me. Regards.

8 – Can’t submit entityform after ajax callback on select element

I followed the advice from this link and migrated the code populating my ajax into buildForm(), and all is well. Select list is populated by ajax and elements are preserved even after form submit. Problem is that I get the following error when I try to submit the form –

The value you selected is not a valid choice

I’ve tried adding the popular '#validated'=TRUE option to my ajax select, but this causes 2 things to happen

  1. My ajax callback only successfully replaces the content of the
    select once, subsequent calls have no effect whatsoever, the old
    content of the select remains
  2. I get a really bad error when I try to
    submit the form "Website encountered an error". Checking the logs
    shows the following:

(client ::1:40776) TypeError: Argument 1 passed to Drupal\Core\Field\WidgetBase::massageFormValues() must be of the type array, string given, called in /home/chibuzo/Software/Dev/Src/Web/tpl_website/web/core/lib/Drupal/Core/Field/WidgetBase.php on line 390 in /home/chibuzo/Software/Dev/Src/Web/tpl_website/web/core/lib/Drupal/Core/Field/WidgetBase.php on line 537 #0 /home/chibuzo/Software/Dev/Src/Web/tpl_website/web/core/lib/Drupal/Core/Field/WidgetBase.php(390): Drupal\Core\Field\WidgetBase->massageFormValues()n#1 /home/chibuzo/Software/Dev/Src/Web/tpl_website/web/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php(232): Drupal\Core\Field\WidgetBase->extractFormValues()

So if I use '#validated' = TRUE, my ajax callback runs only once and shows the error above on form submit,
And if I remove '#validated'=TRUE, my form fails to submit and shows "You have selected an invalid choice" error".
I even tried to update the $form_state variable to contain the same #options values populated by my ajax callback and nothing changes, also $form_state->setRebuild(TRUE) does nothing.

I’m almost giving up the idea of using ajax at all, since I’ve spent more than a week debugging just an ajax select element. First, the ajax callback wasnt being reached at all, now ajax populate happens, but cant submit form. It’s just that I have this feeling that I’ve done 90% of the work involved, its just remaining 1 thing which I dont know. That remaining 10% is what I decided to throw this to the community. I’m sure someone else must know! Thanks for your help, guys…

plugins – Unable to resolve call_user_func_array() expects parameter 1 to be a valid callback, array must have exactly two members

I have a code in a custom plugin which gives the warning:

PHP Warning: call_user_func_array() expects parameter 1 to be a valid callback, array must have exactly two members in public_html/wp-includes/class-wp-hook.php on line 289

The code is as follows:

<?php 
// Backend: Additional pricing option custom field
add_action('woocommerce_product_options_pricing', 'wc_cost_product_field');
function wc_cost_product_field()
{
 woocommerce_wp_text_input(array('id' => '_sale_perc_price', 'class' => 'wc_input_price short', 'label' => __('Sconto (%)', 'woocommerce'), 'desc_tip' => 'true', 'description' => 'Se non vuota, il prezzo in offerta viene calcolato al salvataggio. Se la percentuale di sonto è vuota e il prezzo in offerta è valorizzato, viene calcolato lo sconto in percentuale al salvataggio. Se sia il prezzo in offerta sia lo sconto in percentuale sono vuoto rimarranno vuoti entrambi'));
}

// Backend: Saving product pricing option custom field value
add_action('woocommerce_admin_process_product_object', 'save_product_custom_meta_data', 100, 1);
function save_product_custom_meta_data($product)
{
 $sale_perc = $_POST('_sale_perc_price');
 if (isset($sale_perc)) {
     $sale_perc = absint(sanitize_text_field($_POST('_sale_perc_price')));
 }

 $price = $product->get_regular_price();

 if (!empty($sale_perc)) {
     $product->update_meta_data('_sale_perc_price', $sale_perc);
     $sale_price = $price - ($price * $sale_perc) / 100;
     $sale_price = round($sale_price * 100) / 100;
     $product->set_sale_price($sale_price);
 } else {
     $sale_price = $product->get_sale_price();
     if (!empty($sale_price)) {
         $sale_perc = ($price - $sale_price) * 100 / $price;
         $sale_perc = round($sale_perc * 100) / 100;
         $product->update_meta_data('_sale_perc_price', $sale_perc);
     } else {
         $product->update_meta_data('_sale_perc_price', null);
     }
 }
}

add_filter('woobe_before_update_product_field', 'woobe_before_update_product_field_func', 10, 3);

function woobe_before_update_product_field_func($value, $product_id, $field_key)
{

 if ($field_key === '_sale_perc_price') {
     $price = get_post_meta($product_id, '_regular_price', true);
     $sale_price = $price - ($price * $value) / 100;
     $sale_price = round($sale_price * 100) / 100;
     update_post_meta($product_id, '_sale_price', $sale_price);
 }

 if ($field_key === 'sale_price') {
     $price = get_post_meta($product_id, '_regular_price', true);
     if (!empty($value)) {
         $sale_perc = ($price - $value) * 100 / $price;
         $sale_perc = round($sale_perc * 100) / 100;
         update_post_meta($product_id, '_sale_perc_price', $sale_perc);
     } else {
         update_post_meta($product_id, '_sale_perc_price', 0);
     }
 }

 if ($field_key === 'regular_price') {
     $price = $value;
     $sale_perc = get_post_meta($product_id, '_sale_perc_price', true);
     $sale_price = $price - ($price * $sale_perc) / 100;
     $sale_price = round($sale_price * 100) / 100;
     update_post_meta($product_id, '_sale_price', $sale_price);
 }

 return $value;
}
function add_custom_field_in_bulk_edit_quick_edit()
{
 echo '<div class="inline-edit-group">';
 woocommerce_wp_text_input(array('id' => '_sale_perc_price', 'class' => 'input-text-wrap', 'label' => 'Sconto (%)'));
 echo '</div>';
}
add_action('woocommerce_product_quick_edit_end', 'add_custom_field_in_bulk_edit_quick_edit', 99);
add_action('woocommerce_product_bulk_edit_end', 'add_custom_field_in_bulk_edit_quick_edit', 99);

function save_custom_field_in_bulk_edit_quick_edit($post_id, $post)
{
 // If this is an autosave, our form has not been submitted, so we don't want to do anything.
 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
     return $post_id;
 }
 if ('product' !== $post->post_type) {
     return $post_id;
 }

 $sale_perc = $_POST('_sale_perc_price');
 $price = $_POST('_regular_price');
 $sale_price = $_POST('_sale_price');

 if (!empty($sale_perc)) {
     $sale_perc = absint(sanitize_text_field($_POST('_sale_perc_price')));
     update_post_meta($post_id, '_sale_perc_price', $sale_perc);
     $sale_price = $price - ($price * $sale_perc) / 100;
     $sale_price = round($sale_price * 100) / 100;
     update_post_meta($post_id, '_sale_price', $sale_price);
 } else if (!empty($sale_price)) {
     $sale_perc = ($price - $sale_price) * 100 / $price;
     $sale_perc = round($sale_perc * 100) / 100;
     update_post_meta($post_id, '_sale_perc_price', $sale_perc);
 }
 $_POST('_sale_perc_price') = '';
}

add_action('woocommerce_product_bulk_and_quick_edit', 'save_custom_field_in_bulk_edit_quick_edit', 99, 2);

I think something’s wrong with the call back functions in the hooks, but cannot figure it out. Any suggestions?

8 – Ajax Callback to Update Select List not Working

I have defined couple of fields inside my custom entity basefielddefinitions() like so…
$fields('product_line') = BaseFieldDefinition::create('entity_reference')...

$fields('product') = BaseFieldDefinition::create('entity_reference')....

Then in entity form class (ProductLineForm.php), I try to attach an ajax callback to my product_line select list such that it populates the product select list, like this

    $form('product_line')('#group') = 'details';
    $form('product_line')('#ajax') = (
      'callback' => '::populateProducts',
      'event' => 'change',
      'wrapper' => 'edit-products'
    );

Then my product select list looks like this…

    $form('product')('#group') = 'details';
    $form('product')('#attributes') = (
      'id' => 'edit-products',
    );

and then my populateProducts() function…

  public function populateProducts(array $form, FormStateInterface $form_state) {
    $form('product')('#options') = ('1' => 'One', '2' => 'Two');
    $form_state->setRebuild(TRUE);
    $response = new AjaxResponse();
    $option = "<option value='45'>Just testing</option>";
    $response->addCommand(
      new DrupalCoreAjaxReplaceCommand(
        '#edit-products',
        ($form('product'))
      )
    );
    
    return $response;
  } 

The problem is that nothing whatsoever happens, no signs of any ajax call, and the product select list stays empty as it always been.

(1)Is the the entityform class the right place for me to attach an #ajax call to a field defined in a custom entity? Or do I need a hook? Meanwhile I’ve done a lot of other modifications on the custom fields here in this entity form edit class (like grouping into fieldsets, vertical tabs and even modifying weight (eg $form('product_line')('#weight') = 3 – and they all work, why not $form('product_line')('#ajax')….?

(2) Is there a way of attaching the ajax callback directly inside my custom entity’s basefielddefinitions where I define the fields, I would prefer that…

Really stuck on this one, folks, please could someone help me? Appreciate all your input, Thank you all.

8 – How to add an Ajax call to an element that already has callback set?

I want to add an ajax callback to a form element inside a form_alter, but it already has 2 callbacks assigned to it.

When I review:

$form['payment_information']['payment_method']['#ajax']['callback']

it has 2 callbacks already assigned to it.

If I do this:

$form['payment_information']['payment_method']['#ajax'] = [
  'callback' => '_sia_general_get_fee',
  'event' => 'click',
];

My callback is hit on click; but of course, the other 2 callbacks are wiped out and do not work.

If I add something like this:

$form['payment_information']['payment_method']['#ajax']['callback'][] = '_sia_general_get_fee';

then the other callbacks are called; but mine is not – I suspect since I no longer of an event defined.

I am also not sure how the other ajax calls work when they have no events defined for them.

Is there any way to do this?

c++ – Multithreaded callback – Game Development Stack Exchange

I’m making a multiplayer game where players fight in vehicles, and I am doubting my server architecture. As it will be physics, network and AI intensive I would like to split these 3 topics into their own thread. Perhaps even one thread per AI.

The physics thread will run at a fixed time-step and do the same loop over and over.

  1. Integrate gamestate at fixed timestep of 0,005s (200Hz)
  2. Solve gamestate for constraints and collisions
    One such constraint is a vehicle controller, which is a struct consisting of throttle, steer, brake etc. is applied to a single vehicle.
  3. Callback
    1. The network is called every 6 physics frames, thus the networking runs at ~33Hz
    2. The AI is also called every 6 frames.
      Note: network and AI can be called in lockstep

The AI threads will calculate the next move on a need-by-need basis.

  1. Copy gamestate into private memory
  2. Calculate next move
  3. Update their vehicle controller in the game state

The network thread will

  1. Listen for incoming UDP packets, handle them, apply changes to gamestate such as player’s vehicle controller, bullet spawn
  2. When called for, broadcast the new gamestate to clients
    1. Copy gamestate into private buffer
    2. Create array of differences from last state
      1. Vehicle parts removed/added
      2. Vehicle parts moved/rotated
      3. Players joined/left
      4. Projectile impacts and damages
    3. Pack the differences together and broadcast.
  3. When a new player joins:
    1. grab the last private game state buffer and send it whole
    2. Change gamestate by spawning a vehicle and allocating a controller
  1. Creating threads on the fly has overhead, so I would like to avoid it by pre-creating and “parking” the threads, and calling them when needed. Once called, they do their duty, such as calculate the next move for the AI to make. Then the threads “hibernate”. Note that I don’t want the threads to wait in a busy loop and read some shared memory for “activation”.
  2. The AI and Network threads need to make private copies of the game state, because the physics run so fast the game state might be changed mid-read.
    1. Mitigation 1: swapping game state buffers. Still no guarantee.
    2. Mitigation 2: locking the gamestate. This is a bad idea because the physics should not be held up.

How can I achieve this in C++? Does x86 offer actual interrupts for this? How about other architectures, or are there libraries that do this for me?

Or should I do it another way?

multithreading – C++ callback multithreaded, can unregister itself

With this post, i would like to 1) ask for feedback on below code as it stands:

  • do i apply all best practices for c++20?
  • is it safe?
  • is my way to update a callback from inside a running callback sensible/best?

Based on code and design advice found on stackoverflow (e.g. here), I have written a class that handles listeners registering callbacks to receive messages in multithreaded code (listeners can be added from different threads than the thread that messages are sent from, only one thread every sends messages). This code also needed multiple ways for listeners to unregister themselves:

  1. when the class owning the receiver destructs or is otherwise done receiving: hence add_listener() returns a cookie in the form of a std::list::const_iterator (list because iterators to none of the other elements are invalidated when an element is removed, and other cookies thus stay valid)
  2. when the callback during execution determines it no longer needs further messages, this is handled by returning true (“remove myself please”).

I now run into the situation where a listener callback, when invoked, needs to replace itself with another callback. I can’t call add_listener() as that would deadlock when called from inside an invoked callback. Unless i move to use a std::recursive_mutex instead. That seems heavy.

So instead i have added a replacement list to the broadcaster storing a pair of <listenerCookie, listener> which lists what updates should be done once the current message has been broadcasted to all listeners. The updates are performed at the end of the notify_all function. This guarantees that the old callback is never called again and that the cookie held stays valid but now points to the new callback. But this design seems complicated and unsafe: it required adding an extra member function to the broadcaster class, which should only be called from inside a callback. And that is easy to misuse unless code comments (and the horrible function name :p) saying to only invoke from inside a callback are honored. Or is there a way to ensure a function can only be called by the invoked callback?

Am i missing some simpler solution?

A simpler, but sadly impossible solution i considered was for the callback to return the new callback to register, which would replace the currently registered one (the cookie thus stays valid). But I do not know what my listener’s function signature would then be, as you cannot do something CRTP-like with using statements (using listener = std::function<listener(Message...)>; is invalid) (NB: in reality if this option were possible i’d return a variant with bool as well i guess, as i need to also maintain self-deregistration functionality.)

#include <list>
#include <mutex>
#include <functional>
#include <vector>
#include <utility>

template <class... Message>
class Broadcaster
{
public:
    using listener       = std::function<bool(Message...)>;
    using listenerCookie = typename std::list<listener>::const_iterator;

    listenerCookie add_listener(listener&& r_)
    {
        auto l = lock();
        return targets.emplace(targets.cend(), std::move(r_));
    }
    void remove_listener(listenerCookie it_)
    {
        auto l = lock();
        remove_listener_impl(it_);
    }

    void notify_all(Message... msg_)
    {
        auto l = lock();

        for (auto it = targets.cbegin(), e = targets.cend(); it != e; )
            if ((*it)(msg_...))
                it = remove_listener_impl(it);
            else
                ++it;

        if (!update_list.empty())
        {
            for (auto&& (c_it, r) : update_list)
            {
                // turn cookie into non-const iterator
                auto it = targets.erase(c_it, c_it);    // NB, (c_it, c_it) is an empty range, so nothing is removed
                // update callback
                *it = std::move(r);
            }
            update_list.clear();
        }
    }

    // NB: should only be called from running callback!
    void update_callback_from_inside_callback(listenerCookie it_, listener&& r_)
    {
        update_list.emplace_back(it_, std::move(r_));
    }

private:
    auto lock()
    {
        return std::unique_lock<std::mutex>(m);
    }
    listenerCookie remove_listener_impl(listenerCookie it_)
    {
        return targets.erase(it_);
    }

private:
    std::mutex m;
    std::list<listener> targets;

    std::vector<std::pair<listenerCookie, listener>> update_list;
};