119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati/******************************************************************************
219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *
319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  Copyright (C) 2014 Google, Inc.
419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *
519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  Licensed under the Apache License, Version 2.0 (the "License");
619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  you may not use this file except in compliance with the License.
719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  You may obtain a copy of the License at:
819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *
919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  http://www.apache.org/licenses/LICENSE-2.0
1019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *
1119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  Unless required by applicable law or agreed to in writing, software
1219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  distributed under the License is distributed on an "AS IS" BASIS,
1319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  See the License for the specific language governing permissions and
1519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *  limitations under the License.
1619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati *
1719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati ******************************************************************************/
1819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
1919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati#pragma once
2019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
2119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati#include <stdbool.h>
2219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati#include <stdint.h>
2319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
2419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati#include "osi.h"
2519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
2619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// This module implements the Reactor pattern.
2719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// See http://en.wikipedia.org/wiki/Reactor_pattern for details.
2819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
2919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatistruct reactor_t;
3019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatitypedef struct reactor_t reactor_t;
3119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
3219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatistruct reactor_object_t;
3319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatitypedef struct reactor_object_t reactor_object_t;
3419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
3519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Enumerates the types of events a reactor object is interested
3619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// in responding to.
3719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatitypedef enum {
3819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  REACTOR_INTEREST_READ  = 1,
3919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  REACTOR_INTEREST_WRITE = 2,
4019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  REACTOR_INTEREST_READ_WRITE = 3,
4119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati} reactor_interest_t;
4219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
4319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Enumerates the reasons a reactor has stopped.
4419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatitypedef enum {
4519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  REACTOR_STATUS_STOP,     // |reactor_stop| was called.
4619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  REACTOR_STATUS_TIMEOUT,  // a timeout was specified and the reactor timed out.
4719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  REACTOR_STATUS_ERROR,    // there was an error during the operation.
4819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  REACTOR_STATUS_DONE,     // the reactor completed its work (for the _run_once* variants).
4919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati} reactor_status_t;
5019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
5119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatistruct reactor_object_t {
5219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  void *context;                       // a context that's passed back to the *_ready functions.
5319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  int fd;                              // the file descriptor to monitor for events.
5419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_interest_t interest;         // the event types to monitor the file descriptor for.
5519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
5619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  void (*read_ready)(void *context);   // function to call when the file descriptor becomes readable.
5719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  void (*write_ready)(void *context);  // function to call when the file descriptor becomes writeable.
5819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati};
5919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
6019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Creates a new reactor object. Returns NULL on failure. The returned object
6119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// must be freed by calling |reactor_free|.
6219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatireactor_t *reactor_new(void);
6319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
6419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Frees a reactor object created with |reactor_new|. |reactor| may be NULL.
6519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavativoid reactor_free(reactor_t *reactor);
6619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
6719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Starts the reactor. This function blocks the caller until |reactor_stop| is called
6819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// from another thread or in a callback. |reactor| may not be NULL.
6919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatireactor_status_t reactor_start(reactor_t *reactor);
7019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
7119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Runs one iteration of the reactor. This function blocks until at least one registered object
7219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// becomes ready. |reactor| may not be NULL.
7319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatireactor_status_t reactor_run_once(reactor_t *reactor);
7419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
7519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Same as |reactor_run_once| with a bounded wait time in case no object becomes ready.
7619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatireactor_status_t reactor_run_once_timeout(reactor_t *reactor, timeout_t timeout_ms);
7719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
7819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Immediately unblocks the reactor. This function is safe to call from any thread.
7919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// |reactor| may not be NULL.
8019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavativoid reactor_stop(reactor_t *reactor);
8119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
8219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Registers an object with the reactor. |obj| is neither copied nor is its ownership transferred
8319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// so the pointer must remain valid until it is unregistered with |reactor_unregister|. Neither
8419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// |reactor| nor |obj| may be NULL.
8519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavativoid reactor_register(reactor_t *reactor, reactor_object_t *obj);
8619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
8719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// Unregisters a previously registered object with the |reactor|. Neither |reactor| nor |obj|
8819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati// may be NULL.
8919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavativoid reactor_unregister(reactor_t *reactor, reactor_object_t *obj);
90