/*
 * ptx.h
 * ru cp1251
 *
 *  Created on: 12 δεκ. 2018 γ.
 *      Author: alexrayne <alexraynepe196@gmail.com>
  ------------------------------------------------------------------------
    Copyright (c) alexrayne

   All rights reserved.
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
   - Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   - 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.
   - Neither the name of ARM 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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. *
 *  ---------------------------------------------------------------------
 *  here additional useful Proto-Threads primitives. \sa contiki:sys/pt.h
 *
 *
 */

#ifndef HAL_PORTING_CONTIKI_PTX_H_
#define HAL_PORTING_CONTIKI_PTX_H_


#include <sys/pt.h>

/**
 * Exit the protothread with result Y.
 *
 * 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.
 * \param pt Y result value of protothread. this value MUST be > PT_ENDED
 *                  so that PT_SCHEDULE false with this
 *
 * \hideinitializer
 */
#define PT_RESULT(pt, y)\
  do {                  \
    PT_INIT(pt);        \
    return y;           \
  } while(0)

#define PT_SCHEDULE_WHILE(pt, f )   PT_WAIT_THREAD(pt, (unsigned)f)

/* protothread <f> may results with some meaningful value, that intrests to
 * use later.
 * this macro saves that value to <ok>.
 * scheduling check result surely against PT_xxxx range - from 0.. PT_ENDED
 * */
#define PT_SCHEDULE_RESULT_WHILE(pt, ok, f )\
        PT_WAIT_WHILE( (pt), PT_SCHEDULE( (ok = (f), (unsigned)ok) ) )

#define PT_SPAWN_RESULT(pt, child,  ok, f )\
  do {                      \
        PT_INIT( (child) );\
        PT_SCHEDULE_RESULT_WHILE( (pt),  ok, (f) );\
  } while(0)

/** @brief infer pause for current proccess, that invokes pt.
 * */
#define PT_PAUSE( pt ) do { process_post_pause(); PT_YIELD( pt ); } while(0)



#define PROCESS_SCHEDULE( f )           PROCESS_WAIT_WHILE( PT_SCHEDULE( f ) )

#define PROCESS_SCHEDULE_RESULT(ok, f ) PT_SCHEDULE_RESULT_WHILE(process_pt, ok, f )

#define PROCESS_SPAWN_RESULT(child, ok, f)     PT_SPAWN_RESULT(process_pt, (child), (ok),  f )



/* restarting protothread results to reset an thread state-machine, and
 * going it from start on next poll
 * */
#define PROCESS_RESTART()  \
  do {                      \
    process_poll(process_current);\
    PT_INIT(process_pt);\
    return PT_YIELDED;            \
  } while(0)


/** assign function ptfunc on current process, and restart it with data.
 *  ptfunc starts work on current context
 * */
#define PROCESS_NEXT( ptfunc, data)  \
  do {                      \
    process_poll(process_current);\
    process_current->thread = ptfunc;\
    PT_INIT(process_pt);\
    ptfunc(process_pt, PROCESS_EVENT_INIT, data);\
    return PT_YIELDED;            \
  } while(0)





#endif /* HAL_PORTING_CONTIKI_PTX_H_ */
