The most lightweight C-CO libraries: Protothreads

Source: Internet
Author: User

@20150228

http://blog.csdn.net/weiwangchao_/article/details/7777385

The benefits of the process are no more to say, as the relative concept of function call/return, it allows us to think about the way the problem goes through a change. Now we are concerned about C, because of the characteristics of C itself, the introduction of the process will be a challenge. Countless pioneers have shed their blood for this goal, so we have libtask and so on. What is mentioned here is one of the most lightweight implementation of the process: Protothreads (home: http://www.sics.se/~adam/pt/). The so-called lightweight, that is, the function can no longer be streamlined, almost the original language level. --indeed, this minimalist brings some cumbersome inconvenience to use, but before you quit, take a look at its advantages:

    1. It is not dependent on any library (including the C standard library and OS, yes, it can be used in bootloader), not even the "library" itself, in fact the entire implementation is only. h files.
    2. A. h file is only 5, and the total number of valid rows is 100 orders of magnitude (version 1.4).
    3. Then add that most of those lines are also macro definitions, so using this library causes the program to expand basically negligible.
    4. The memory overhead of each process is only as large as one pointer.

To tell the truth, this form of so-called "library" the best way to use is to refer to its source code and then direct reference to their own programs. Such a bit of code can achieve the function of the process, and its principle is a layer of window paper. In fact, Protothreads uses two ways to implement the co-process, and you can choose one of the ways:

    1. Implemented with the switch statement.
    2. Implemented with the GCC extension syntax.

The former is good in generality but inefficient, and more inconvenient to use, the latter opposite. The default is the former, I tend to the latter (the latter MinGW also support), which is attributed to the use of the GCC, and the latter from the thought is indeed more concise, no trick meaning. The principle narrative here is also dominated by the latter.

This "extended syntax", like a scourge, is actually: you can save the label address to a variable. The label is the Goto label, which is the raves Goto. As follows:

Begin:    printf ("This is a Messagen");    /* goto begin; --we were supposed to use this. */    void *p = &&begin;    Goto *p;

&& instead of address and address ^_^ instead of extending the syntax, this operator is used for the label, which means taking its address in the code snippet, which means getting a pointer. A pointer to a code snippet, the first reaction is a function pointer, but this is not because it does not point to the entry of a function, but to its abdomen. This pointer type C does not exist, and GCC does not want to make things big, the whole new data type, so with void * take-all. This value can be used as normal data to fiddle with, and finally by Goto *p, to jump from anywhere else to the address to execute.

Perhaps remember, C's Goto is not able to cross the function boundary, from the theoretical point of view this is called to ensure that single-entry single-out of the structured programming, from the bottom of the implementation angle, it is guaranteed that the stack frame is not chaotic, that is: if goto another function of the code snippet, but the other function's stack frame is not ready, Then the purpose function will be chaotic when accessing local data. This confusion, which was not possible, became possible with the support of this extended grammar. This is a point to note that when using extended goto statements You should also be careful not to cross the function boundaries (of course, if you BT to understand the stack frame protocol and try to manually build the stack frame, then I did not say ^_^).

Protothreads Library to the implementation of the process, it is also easy to say, and see a function of the path of the schematic:

int foo (struct pt *p) {    pt_begin (p);        ... /* Code Snippet 1 *    /Pt_yield (p);        ... /* Code Snippet 2 *    /Pt_end (p);}

This function is called every time the process is re-entered, and the macro that starts with the Pt_ function determines which part of the function body should be executed each time it is called. For example, if you call two Foo, the first time you execute code snippet 1, the second time you execute code snippet 2. The principle is as follows:

struct struct PT In fact there is only a void * type member, which is the legendary "cost of a pointer", each association has a corresponding this object. The pointer is set to NULL at initialization (by another macro pt_init elsewhere), and in the Foo function, Pt_begin checks the pointer, or NULL, to indicate that it is the first time to start the process and do nothing. Next encounter Pt_yield, that is, the co-process hangs the primitive language. This macro defines a label inside and immediately saves the label in the PT structure. In this way, there may be several ways to enter, one in order to do this, and two to Goto from elsewhere. This so-called elsewhere, in fact, is in Pt_begin. If it checks that PT is not empty, it immediately goto past. Now Pt_yield to make further judgments based on the way to get here, and if it is natural to do so, the Reeturn is immediately out of the function. Otherwise, it is just re-entered back, continuing with the code snippet below 2. How is this judgment carried out? --by a flag, pt_begin each call is preceded by a flag, and Pt_yield clears the flag before the label. In this way, after the label, Pt_yield can be judged, if the flag is not, then it is natural to do this, if the sign exists, it is from the Pt_begin Goto. --It's a super-lightweight version of setjmp.

As for Pt_end, its effect is to return the state of the coprocessor except for the PT pointer. In fact, the return in Pt_yield is also a value, the reason Foo function to declare as int, is to each call Foo can get the current state of the process, is suspended, ended, or halfway out, and so on.
It should be noted that since the Foo function is called back every time the re-entry is made, there is no State left in the Foo function and the contents are lost if the local variable is defined. Well...... This is what I mean by "cumbersome and inconvenient", you need to make all the process state exist as external variables, the typical practice is to encapsulate a struct as the second parameter of the function. Well, after all, C is close to the bottom of the language, let it automatically behind you to create a lot of variables, or a lot of local stack, or rather than your own precise control of the use of each piece of memory, right? After all, you can't use scripting language to see C ^_^

Now that you've created a lot of them in this way, then it's a simple way to make them work, and the rotation schedule is incredibly simple:

while (1) {    foo1 (p1);    Foo2 (p2);    ...    Foon (PN);}

This is the main loop of the scheduler, which only needs to invoke the entry function of each process in turn.

The above describes the core content of the Protothreads library, in fact, the library also contains dynamic co-Cheng Jianli, inter-process communication facilities, for a such a thin library, is still quite surprising. Finally, in order to emphasize its thin again, here is a list of all its header files:

        Lc-addrlabels.h        using the GCC syntax to extend the implementation of the        LC-SWITCH.H Foundation        lc.h                  The value of the file exists only to select one of the two        Pt.h The                 realization of        pt-sem.h inter-               process communication (semaphore) based on Lc.h's real implementation of the co-process facilities

The most lightweight C-CO libraries: Protothreads

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.