Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Callback Functions With User Supplied Data Pointers #14

Closed
NZSmartie opened this issue Mar 26, 2017 · 4 comments · Fixed by #23
Closed

Callback Functions With User Supplied Data Pointers #14

NZSmartie opened this issue Mar 26, 2017 · 4 comments · Fixed by #23

Comments

@NZSmartie
Copy link
Contributor

I propose that CoAP_CreateResource(...) (used to register resources) to have an additional opaque void* pUserData parameter that will be included in CoAP_ResourceHandler_fPtr_t and CoAP_ResourceNotifier_fPtr_t. This would allow the application to register multiple resources and pass along identifying information in pUserData to allow the apllication to quickly use without the need for a lookup table with the URI of the resource.

I'll be happy to create a PR if this idea is good. Unless another solution is preferred?

Use Case
I have a for loop that generates 100 resources, that each has small data associated with it. would be nice to pass a pointer to the data to CoAP_Res_t (through CoAP_CreateResource) that is then passed to a single resource handler for all 100 resources. to quickly access the requried data without needing to parse the resource URI and fetch the associated data.

@niondir
Copy link
Member

niondir commented Mar 26, 2017

I have worked with a lot of different Web API's and must say I like to keep the ResourceHandler as simple as possible and prefer to stick with a simple Handle(Reqeust, Response);

I know the following pattern from other languages. Maybe it can help you a bit with your issue:

// Register like this:
CoAP_CreateResource(HandleWithData);

HandleWithData(Request req, Response res) {
    void* pUserData = FindUserData();
    CustomHandler(req, res, pUserData);
}

CustomHandler(Request req, Response res, void* pUserData) {
    // Implement what you need
}

You would probably need 100 different HandleWithData functions, or implement some lookup logic inside. Code generation or maybe a macro could help here. But the actual logic must be implemented only once in CustomHandler.

There might be use cases where a runtime lookup of pUserData is better and other use cases where static lookups with multiple HandleWithData like functions is better suited for an application.

I also don't like the idea of handling an additional void pointer in the context of every resource handler. It will increase the memory footprint of the lib and might only be used by a minority of applications (can't really judge this yet, but it's hard to take it back later on). Void pointers might also lead to nasty runtime bugs and are hard to track.

What I like is the context concept of GOs that is also used in the HTTP package: https://golang.org/pkg/context/
Maybe we could have something like this in future. But it would also require some pattern like the one above for actually "fill" the context with user data.

@NZSmartie
Copy link
Contributor Author

Heh, I wrote this while a bit sleep deprived last night. I may have somehow forgotten that CoAP_CreateResource() returns CoAP_Res_t* which is pretty easy to store in a lookup table... 😅

@NZSmartie
Copy link
Contributor Author

I'm still not quite with it it seems. ☕️

Would adding CoAP_Res_t to CoAP_ResourceHandler_fPtr_t be okay? I can use that pointer to lookup associated data (assuming the resource pointer itself is immutable)

@NZSmartie NZSmartie reopened this Mar 26, 2017
@niondir
Copy link
Member

niondir commented Mar 27, 2017

CoAP_ResourceHandler_fPtr_t already returns CoAP_HandlerResult_t which is used to determine if the Reponse is delayed or not. Actually I would prefer to have this mechanism on the Response object. Leading to CoAP_ResourceHandler_fPtr_t returning void

But where would you use the return value of CoAP_ResourceHandler_fPtr_t in your application anyway? The return value is only interpreted inside the lib, or did I missed something?

What we could do is to atatch the CoAP_Res_t* pointer, which is known to the lib anyway to the request object, to have an alternativ way to identify the resource, beside the URL.

€ ahh I guess thats what you meant anyway. So I prefer adding it to the Request object instead of an extra parameter :)
€2: Which in fact is CoAP_Message_t and CoAP_Observer_t. The latter one should be obsolet one day to get rid of a separate method signature for notification handlers.

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

Successfully merging a pull request may close this issue.

2 participants