protothread/pt.h

316 lines
7.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2004-2005, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: pt.h,v 1.7 2006/10/02 07:52:56 adam Exp $
*/
/**
* \addtogroup pt
* @{
*/
/**
* \file
* Protothreads implementation.
* \author
* Adam Dunkels <adam@sics.se>
*
*/
#ifndef __PT_H__
#define __PT_H__
#include "lc.h"
struct pt {
lc_t lc;
};
#define PT_WAITING 0
#define PT_YIELDED 1
#define PT_EXITED 2
#define PT_ENDED 3
/**
* \name <20><>ʼ<EFBFBD><CABC>
* @{
*/
/**
* <20><>ʼ<EFBFBD><CABC>protothread<61>߳<EFBFBD>
*
* <20><>ʼ<EFBFBD><CABC>protothread<61>̡߳<DFB3><CCA1><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD>ʼִ<CABC><D6B4>ԭ<EFBFBD><D4AD><EFBFBD>߳<EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD>ɡ<EFBFBD>
*
* \param pt ָ<><D6B8>protothread<61>߳̿<DFB3><CCBF>ƽ<C6BD><E1B9B9>ָ<EFBFBD><D6B8>
*
* \sa PT_SPAWN()
*
* \hideinitializer
*/
#define PT_INIT(pt) LC_INIT((pt)->lc)
/** @} */
/**
* \name <20><><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>
* @{
*/
/**
* <20><><EFBFBD><EFBFBD>protothread<61>̡߳<DFB3>
*
* <20>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>protothread<61>̡߳<DFB3><CCA1><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ô˺<C3B4><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>protothread<61>߳<EFBFBD>
*
* \param name_args ʵ<><CAB5>protothread<61>̵߳<DFB3> C <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƺͲ<C6BA><CDB2><EFBFBD><EFBFBD><EFBFBD>
*
* \hideinitializer
*/
#define PT_THREAD(name_args) char name_args
/**
* <20><>ʵ<EFBFBD><CAB5>protothread<61>̵߳<DFB3> C <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>protothread<61>̵߳Ŀ<CCB5>ʼ
*
* <20>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>protothread<61>̵߳<DFB3><CCB5><EFBFBD><EFBFBD><EFBFBD><E3A1A3>Ӧ<EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>protothread<61>̵߳ĺ<CCB5><C4BA><EFBFBD><EFBFBD>Ŀ<EFBFBD>ͷ<EFBFBD><CDB7>
* ÿ<>ε<EFBFBD><CEB5><EFBFBD> protothread ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4> PT_BEGIN<49><4E><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> C <20><><EFBFBD>
*
* \param pt ָ<><D6B8>ԭ<EFBFBD><D4AD><EFBFBD>߳̿<DFB3><CCBF>ƽ<C6BD><E1B9B9>ָ<EFBFBD>
*
* \hideinitializer
*/
#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
/**
* <20><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>̵߳Ľ<CCB5><C4BD><EFBFBD><EFBFBD><EFBFBD>
*
* <20>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>߳̽<DFB3><CCBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD> PT_BEGIN<49><4E><EFBFBD><EFBFBD> <20><>һ<EFBFBD><D2BB>ʹ<EFBFBD>á<EFBFBD>
*
* \param pt ָ<><D6B8>ԭ<EFBFBD><D4AD><EFBFBD>߳̿<DFB3><CCBF>ƽ<C6BD><E1B9B9>ָ<EFBFBD>
*
* \hideinitializer
*/
#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
PT_INIT(pt); return PT_ENDED; }
/** @} */
/**
* \name <20><>ֹ<EFBFBD>ȴ<EFBFBD>
* @{
*/
/**
* <20><>ֹ<EFBFBD><D6B9><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
*
* <20>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>̣߳<DFB3>ֱ<EFBFBD><D6B1>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
*
* \param pt ָ<><D6B8>ԭ<EFBFBD><D4AD><EFBFBD>߳̿<DFB3><CCBF>ƽ<C6BD><E1B9B9>ָ<EFBFBD><D6B8>
* \param condition <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \hideinitializer
*/
#define PT_WAIT_UNTIL(pt, condition) \
do { \
LC_SET((pt)->lc); \
if(!(condition)) { \
return PT_WAITING; \
} \
} while(0)
/**
* <20><>ֹ<EFBFBD><D6B9><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>
*
* <20>˹<EFBFBD><CBB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ʱ<EFBFBD><CAB1>ֹ<EFBFBD><D6B9><EFBFBD>ȴ<EFBFBD>. See
* PT_WAIT_UNTIL().
*
* \param pt ָ<><D6B8>ԭ<EFBFBD><D4AD><EFBFBD>߳̿<DFB3><CCBF>ƽ<C6BD><E1B9B9>ָ<EFBFBD><D6B8>
* \param cond <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \hideinitializer
*/
#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
/** @} */
/**
* \name <20>ֲ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>߳<EFBFBD>
* @{
*/
/**
* <20><>ֹ<EFBFBD><D6B9><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD>ɡ<EFBFBD>
*
* This macro schedules a child protothread. The current protothread
* will block until the child protothread completes.
*
* \note The child protothread must be manually initialized with the
* PT_INIT() function before this function is used.
*
* \param pt A pointer to the protothread control structure.
* \param thread The child protothread with arguments
*
* \sa PT_SPAWN()
*
* \hideinitializer
*/
#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
/**
* Spawn a child protothread and wait until it exits.
*
* This macro spawns a child protothread and waits until it exits. The
* macro can only be used within a protothread.
*
* \param pt A pointer to the protothread control structure.
* \param child A pointer to the child protothread's control structure.
* \param thread The child protothread with arguments
*
* \hideinitializer
*/
#define PT_SPAWN(pt, child, thread) \
do { \
PT_INIT((child)); \
PT_WAIT_THREAD((pt), (thread)); \
} while(0)
/** @} */
/**
* \name Exiting and restarting
* @{
*/
/**
* Restart the protothread.
*
* This macro will block and cause the running protothread to restart
* its execution at the place of the PT_BEGIN() call.
*
* \param pt A pointer to the protothread control structure.
*
* \hideinitializer
*/
#define PT_RESTART(pt) \
do { \
PT_INIT(pt); \
return PT_WAITING; \
} while(0)
/**
* Exit the protothread.
*
* This macro causes the protothread to exit. If the protothread was
* spawned by another protothread, the parent protothread will become
* unblocked and can continue to run.
*
* \param pt A pointer to the protothread control structure.
*
* \hideinitializer
*/
#define PT_EXIT(pt) \
do { \
PT_INIT(pt); \
return PT_EXITED; \
} while(0)
/** @} */
/**
* \name Calling a protothread
* @{
*/
/**
* Schedule a protothread.
*
* This function shedules a protothread. The return value of the
* function is non-zero if the protothread is running or zero if the
* protothread has exited.
*
* \param f The call to the C function implementing the protothread to
* be scheduled
*
* \hideinitializer
*/
#define PT_SCHEDULE(f) ((f) < PT_EXITED)
/** @} */
/**
* \name Yielding from a protothread
* @{
*/
/**
* Yield from the current protothread.
*
* This function will yield the protothread, thereby allowing other
* processing to take place in the system.
*
* \param pt A pointer to the protothread control structure.
*
* \hideinitializer
*/
#define PT_YIELD(pt) \
do { \
PT_YIELD_FLAG = 0; \
LC_SET((pt)->lc); \
if(PT_YIELD_FLAG == 0) { \
return PT_YIELDED; \
} \
} while(0)
/**
* \brief Yield from the protothread until a condition occurs.
* \param pt A pointer to the protothread control structure.
* \param cond The condition.
*
* This function will yield the protothread, until the
* specified condition evaluates to true.
*
*
* \hideinitializer
*/
#define PT_YIELD_UNTIL(pt, cond) \
do { \
PT_YIELD_FLAG = 0; \
LC_SET((pt)->lc); \
if((PT_YIELD_FLAG == 0) || !(cond)) { \
return PT_YIELDED; \
} \
} while(0)
/** @} */
#endif /* __PT_H__ */
/** @} */