You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mynewt.apache.org by "paul@wrada.com" <pa...@wrada.com> on 2018/06/25 02:10:16 UTC
shell commands for multiple instantiated modules
I'm checking with the group on how folks have done this in the past in case I am missing something. Also proposing how I would solve the problem looking for feedback.
I have a module that you may want to instantiate more than once (create two or more objects). For example suppose I have a device driver that may instantiate multiple times but with different context.
I’m trying to determine how I will provide shell commands for them. I have a few options.
1. use the first argument of the shell command as the object instance and queue the object onto some list that I can search in the command to execute the command on the right object
2. Try to modify the the shell command to include a void * somewhere in the registration and have the shell commands pass it back during execution.
3. Have the callback return the module name string which I can cast back or search for combining the flexibility of #1 and #2
In the first option I would queue my instance objects on a queue and then search for them by name or number
* foo 0 reset
* foo 1 reset
When there is only once instance (most typical) then the command has the burden of carrying the extra notation or I have to provide provisional processing to do some default behavior when the number is left out of the command. For this functionality I need to queue the objects which is not currently necessary (its only a few bytes for an SLIST).
In the second choice I could have the following changes to shell
* include a void * in the shell_register that is passed in the callback like
* typedef int (*shell_cmd_func_t)(int argc, char *argv[], void *arg);
* int shell_register(const char *shell_name, const struct shell_cmd *shell_commands, void *arg)
* shell_register(“sample_object0", cmd, (void*) &obj0)
* shell_register(“sample_object1", cmd, (void*) &obj1)
* Modify the internal definition of the shell module to have
* struct shell_module {
* const char *name;
* const struct shell_cmd *commands;
* void *arg;
* };
In this method the commands would look like this
* foo0 reset
* foo1 reset
Of course, the first instance of this could also just be called foo and then the latter could have numbers
* Foo reset
* foo1 reset
* foo2 reset
NOTE: because of mempools, logs and stats I already keep a char *name in the object to differentiate each instance (e.g. foo0 foo1 etc). So I already have the means to pass the name.
In the 3rd option, it would not change any of the APIs to register or any of the internal structures , but will still require a change to the callback to pass the string back to the caller like this
* typedef int (*shell_cmd_func_t)(int argc, char *argv[], const char *shell_name);
And I could cast that back to my object using something like
Struct foo {
/* blah blah */
char name[32];
};
Struct foo *pf = (struct foo*) ( (uint8_t*) shell_name - (int) ((struct foo *) 0)->name))
Or I could keep them on a list and search the list for a matching string in shell_name.
In short
* Option 1 — requires no change to shell API. Requires queueing objects and some special command processing code
* Option 2 — simple to use, but requires API change and an extra void * storage for each shell module
* Option 3 — more complicated to use, requires API change but does not require extra storage for each shell module
Re: shell commands for multiple instantiated modules
Posted by will sanfilippo <wi...@runtime.io>.
Not sure I have a strong opinion on this one. My initial reaction was option 1 but I can understand why some of the other options might be better.
> On Jun 25, 2018, at 4:07 AM, Michał Narajowski <mi...@codecoup.pl> wrote:
>
> Hi Paul,
>
> IMO Option 1 seems like the best option here. I don't think the special
> command processing code will require a lot of work. Of course, if you think
> that Option 2 is better for your use case you can implement it and submit a
> PR.
>
> BR
> Michał Narajowski
>
> pon., 25 cze 2018 o 04:10 paul@wrada.com <pa...@wrada.com> napisał(a):
>
>> I'm checking with the group on how folks have done this in the past in
>> case I am missing something. Also proposing how I would solve the problem
>> looking for feedback.
>>
>> I have a module that you may want to instantiate more than once (create
>> two or more objects). For example suppose I have a device driver that may
>> instantiate multiple times but with different context.
>>
>> I’m trying to determine how I will provide shell commands for them. I have
>> a few options.
>>
>> 1. use the first argument of the shell command as the object instance
>> and queue the object onto some list that I can search in the command to
>> execute the command on the right object
>> 2. Try to modify the the shell command to include a void * somewhere in
>> the registration and have the shell commands pass it back during execution.
>> 3. Have the callback return the module name string which I can cast
>> back or search for combining the flexibility of #1 and #2
>>
>> In the first option I would queue my instance objects on a queue and then
>> search for them by name or number
>>
>> * foo 0 reset
>> * foo 1 reset
>>
>> When there is only once instance (most typical) then the command has the
>> burden of carrying the extra notation or I have to provide provisional
>> processing to do some default behavior when the number is left out of the
>> command. For this functionality I need to queue the objects which is not
>> currently necessary (its only a few bytes for an SLIST).
>>
>> In the second choice I could have the following changes to shell
>>
>> * include a void * in the shell_register that is passed in the
>> callback like
>> * typedef int (*shell_cmd_func_t)(int argc, char *argv[], void
>> *arg);
>>
>> * int shell_register(const char *shell_name, const struct shell_cmd
>> *shell_commands, void *arg)
>>
>> * shell_register(“sample_object0", cmd, (void*) &obj0)
>>
>> * shell_register(“sample_object1", cmd, (void*) &obj1)
>> * Modify the internal definition of the shell module to have
>> * struct shell_module {
>> * const char *name;
>> * const struct shell_cmd *commands;
>> * void *arg;
>> * };
>>
>> In this method the commands would look like this
>>
>> * foo0 reset
>> * foo1 reset
>>
>> Of course, the first instance of this could also just be called foo and
>> then the latter could have numbers
>>
>> * Foo reset
>> * foo1 reset
>> * foo2 reset
>>
>> NOTE: because of mempools, logs and stats I already keep a char *name in
>> the object to differentiate each instance (e.g. foo0 foo1 etc). So I
>> already have the means to pass the name.
>>
>> In the 3rd option, it would not change any of the APIs to register or any
>> of the internal structures , but will still require a change to the
>> callback to pass the string back to the caller like this
>>
>> * typedef int (*shell_cmd_func_t)(int argc, char *argv[], const char
>> *shell_name);
>>
>> And I could cast that back to my object using something like
>>
>> Struct foo {
>> /* blah blah */
>> char name[32];
>> };
>>
>> Struct foo *pf = (struct foo*) ( (uint8_t*) shell_name - (int) ((struct
>> foo *) 0)->name))
>>
>> Or I could keep them on a list and search the list for a matching string
>> in shell_name.
>>
>> In short
>>
>> * Option 1 — requires no change to shell API. Requires queueing
>> objects and some special command processing code
>> * Option 2 — simple to use, but requires API change and an extra void
>> * storage for each shell module
>> * Option 3 — more complicated to use, requires API change but does not
>> require extra storage for each shell module
>>
>>
>>
>>
>>
>>
>>
>>
Re: shell commands for multiple instantiated modules
Posted by Michał Narajowski <mi...@codecoup.pl>.
Hi Paul,
IMO Option 1 seems like the best option here. I don't think the special
command processing code will require a lot of work. Of course, if you think
that Option 2 is better for your use case you can implement it and submit a
PR.
BR
Michał Narajowski
pon., 25 cze 2018 o 04:10 paul@wrada.com <pa...@wrada.com> napisał(a):
> I'm checking with the group on how folks have done this in the past in
> case I am missing something. Also proposing how I would solve the problem
> looking for feedback.
>
> I have a module that you may want to instantiate more than once (create
> two or more objects). For example suppose I have a device driver that may
> instantiate multiple times but with different context.
>
> I’m trying to determine how I will provide shell commands for them. I have
> a few options.
>
> 1. use the first argument of the shell command as the object instance
> and queue the object onto some list that I can search in the command to
> execute the command on the right object
> 2. Try to modify the the shell command to include a void * somewhere in
> the registration and have the shell commands pass it back during execution.
> 3. Have the callback return the module name string which I can cast
> back or search for combining the flexibility of #1 and #2
>
> In the first option I would queue my instance objects on a queue and then
> search for them by name or number
>
> * foo 0 reset
> * foo 1 reset
>
> When there is only once instance (most typical) then the command has the
> burden of carrying the extra notation or I have to provide provisional
> processing to do some default behavior when the number is left out of the
> command. For this functionality I need to queue the objects which is not
> currently necessary (its only a few bytes for an SLIST).
>
> In the second choice I could have the following changes to shell
>
> * include a void * in the shell_register that is passed in the
> callback like
> * typedef int (*shell_cmd_func_t)(int argc, char *argv[], void
> *arg);
>
> * int shell_register(const char *shell_name, const struct shell_cmd
> *shell_commands, void *arg)
>
> * shell_register(“sample_object0", cmd, (void*) &obj0)
>
> * shell_register(“sample_object1", cmd, (void*) &obj1)
> * Modify the internal definition of the shell module to have
> * struct shell_module {
> * const char *name;
> * const struct shell_cmd *commands;
> * void *arg;
> * };
>
> In this method the commands would look like this
>
> * foo0 reset
> * foo1 reset
>
> Of course, the first instance of this could also just be called foo and
> then the latter could have numbers
>
> * Foo reset
> * foo1 reset
> * foo2 reset
>
> NOTE: because of mempools, logs and stats I already keep a char *name in
> the object to differentiate each instance (e.g. foo0 foo1 etc). So I
> already have the means to pass the name.
>
> In the 3rd option, it would not change any of the APIs to register or any
> of the internal structures , but will still require a change to the
> callback to pass the string back to the caller like this
>
> * typedef int (*shell_cmd_func_t)(int argc, char *argv[], const char
> *shell_name);
>
> And I could cast that back to my object using something like
>
> Struct foo {
> /* blah blah */
> char name[32];
> };
>
> Struct foo *pf = (struct foo*) ( (uint8_t*) shell_name - (int) ((struct
> foo *) 0)->name))
>
> Or I could keep them on a list and search the list for a matching string
> in shell_name.
>
> In short
>
> * Option 1 — requires no change to shell API. Requires queueing
> objects and some special command processing code
> * Option 2 — simple to use, but requires API change and an extra void
> * storage for each shell module
> * Option 3 — more complicated to use, requires API change but does not
> require extra storage for each shell module
>
>
>
>
>
>
>
>