Skip to content

include/tenzr/execution/stream.h

Namespaces

Name
tenzr
tenzr::execution

Classes

Name
struct tenzr::execution::StreamEventState
Shared readiness state for a stream event, holding the ready flag, the PJRT event, and completion callbacks.
class tenzr::execution::StreamEvent
Handle to a recorded point in a stream's work, used to query completion or to make later work wait.
class tenzr::execution::ExecutionStream
Serialized work queue backed by a worker thread, used to submit and synchronize device work.

Source code

// Copyright 2026 The Tenzr Project Authors
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef TENZR_EXECUTION_STREAM_H_
#define TENZR_EXECUTION_STREAM_H_

#include <xla/pjrt/c/pjrt_c_api.h>

#include <atomic>
#include <condition_variable>
#include <cstdint>
#include <exception>
#include <functional>
#include <future>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>
#include <type_traits>
#include <vector>

#include "tenzr/common/error.h"

namespace tenzr::execution {

  class ExecutionStream;

  struct StreamEventState {
    std::atomic<bool> ready{false};

    std::mutex mutex;

    std::condition_variable cv;

    std::vector<std::function<void()>> callbacks;

    PJRT_Event* pjrt_event{nullptr};

    void SetReady();

    void Wait();

    bool IsReady() const;

    void AddCallback(std::function<void()> cb);
  };

  class StreamEvent {
   public:
    StreamEvent();

    explicit StreamEvent(PJRT_Event* pjrt_event);

    ~StreamEvent() = default;

    StreamEvent(const StreamEvent&) = default;
    StreamEvent& operator=(const StreamEvent&) = default;
    StreamEvent(StreamEvent&&) noexcept = default;
    StreamEvent& operator=(StreamEvent&&) noexcept = default;

    void Record(ExecutionStream& stream);

    bool Query() const;

    void Synchronize();

    std::shared_ptr<StreamEventState> State() const { return state_; }

   private:
    std::shared_ptr<StreamEventState> state_;
  };

  class ExecutionStream : public std::enable_shared_from_this<ExecutionStream> {
   public:
    explicit ExecutionStream(int stream_id = 0, int device_id = 0);

    ~ExecutionStream();

    ExecutionStream(const ExecutionStream&) = delete;
    ExecutionStream& operator=(const ExecutionStream&) = delete;

    int StreamId() const { return stream_id_; }

    int DeviceId() const { return device_id_; }

    void RecordEvent(StreamEvent& event);

    void WaitEvent(const StreamEvent& event);

    void Synchronize();

    void Submit(std::function<void()> task);

    template <typename F> auto AsyncSubmit(F&& task) {
      using Ret = std::invoke_result_t<F>;
      auto prom = std::make_shared<std::promise<Ret>>();
      auto fut = prom->get_future();

      Submit([prom, captured_task = std::forward<F>(task)]() mutable {
#if TENZR_EXCEPTIONS_ENABLED
        try {
          if constexpr (std::is_void_v<Ret>) {
            captured_task();
            prom->set_value();
          } else {
            prom->set_value(captured_task());
          }
        } catch (...) {
          prom->set_exception(std::current_exception());
        }
#else
        if constexpr (std::is_void_v<Ret>) {
          captured_task();
          prom->set_value();
        } else {
          prom->set_value(captured_task());
        }
#endif
      });

      return fut;
    }

    static ExecutionStream& DefaultStream(int device_id = 0);

    static std::shared_ptr<ExecutionStream> Create(int device_id = 0);

   private:
    void WorkerLoop();

    int stream_id_{0};
    int device_id_{0};
    std::atomic<bool> stop_{false};
    std::thread worker_;
    std::mutex queue_mutex_;
    std::condition_variable queue_cv_;
    std::condition_variable empty_cv_;
    std::queue<std::function<void()>> tasks_;
    size_t active_tasks_{0};
  };

}  // namespace tenzr::execution

#endif  // TENZR_EXECUTION_STREAM_H_