text:
// Copyright 2017 The Ray Authors.
//
// 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
//
//  http://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.

#include "io_ray_runtime_actor_NativeActorHandle.h"

#include <jni.h>

#include "jni_utils.h"
#include "ray/common/id.h"
#include "ray/core_worker/actor_handle.h"
#include "ray/core_worker/common.h"
#include "ray/core_worker/core_worker.h"
#include "ray/core_worker/core_worker_process.h"

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_io_ray_runtime_actor_NativeActorHandle_nativeGetLanguage(
    JNIEnv *env, jclass o, jbyteArray actorId) {
  auto actor_id = JavaByteArrayToId<ActorID>(env, actorId);
  const auto native_actor_handle =
      CoreWorkerProcess::GetCoreWorker().GetActorHandle(actor_id);
  return native_actor_handle->ActorLanguage();
}

JNIEXPORT jobject JNICALL
Java_io_ray_runtime_actor_NativeActorHandle_nativeGetActorCreationTaskFunctionDescriptor(
    JNIEnv *env, jclass o, jbyteArray actorId) {
  auto actor_id = JavaByteArrayToId<ActorID>(env, actorId);
  const auto native_actor_handle =
      CoreWorkerProcess::GetCoreWorker().GetActorHandle(actor_id);
  auto function_descriptor = native_actor_handle->ActorCreationTaskFunctionDescriptor();
  return NativeRayFunctionDescriptorToJavaStringList(env, function_descriptor);
}

JNIEXPORT jbyteArray JNICALL Java_io_ray_runtime_actor_NativeActorHandle_nativeSerialize(
    JNIEnv *env, jclass o, jbyteArray actorId, jbyteArray actorHandleId) {
  auto actor_id = JavaByteArrayToId<ActorID>(env, actorId);
  std::string output;
  ObjectID actor_handle_id;
  Status status = CoreWorkerProcess::GetCoreWorker().SerializeActorHandle(
      actor_id, &output, &actor_handle_id);
  env->SetByteArrayRegion(actorHandleId,
                          0,
                          ObjectID::kLength,
                          reinterpret_cast<const jbyte *>(actor_handle_id.Data()));
  THROW_EXCEPTION_AND_RETURN_IF_NOT_OK(env, status, nullptr);
  return NativeStringToJavaByteArray(env, output);
}

JNIEXPORT jbyteArray JNICALL
Java_io_ray_runtime_actor_NativeActorHandle_nativeDeserialize(JNIEnv *env,
                                                              jclass o,
                                                              jbyteArray data) {
  auto buffer = JavaByteArrayToNativeBuffer(env, data);
  RAY_CHECK(buffer->Size() > 0);
  auto binary = std::string(reinterpret_cast<char *>(buffer->Data()), buffer->Size());
  auto actor_id = CoreWorkerProcess::GetCoreWorker().DeserializeAndRegisterActorHandle(
      binary, /*outer_object_id=*/ObjectID::Nil());

  return IdToJavaByteArray<ActorID>(env, actor_id);
}

JNIEXPORT void JNICALL
Java_io_ray_runtime_actor_NativeActorHandle_nativeRemoveActorHandleReference(
    JNIEnv *env, jclass clz, jbyteArray actorId) {
  // We can't control the timing of Java GC, so it's normal that this method is called but
  // core worker is shutting down (or already shut down). If we can't get a core worker
  // instance here, skip calling the `RemoveLocalReference` method.
 auto core_worker = CoreWorkerProcess::TryGetWorker();
  if (core_worker != nullptr) {
    const auto actor_id = JavaByteArrayToId<ActorID>(env, actorId);
    core_worker->RemoveActorHandleReference(actor_id);
  }
}

#ifdef __cplusplus
}
#endif

redpajama_set_name: RedPajamaGithub


text:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.Design;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Extensions.DependencyInjection;
using Ninject;
using Ninject.Activation;
using Ninject.Activation.Caching;
using Ninject.Activation.Strategies;
using Ninject.Injection;
using Ninject.Modules;
using Ninject.Parameters;
using Ninject.Planning;
using Ninject.Planning.Bindings;
using Ninject.Planning.Bindings.Resolvers;
using Ninject.Planning.Strategies;
using Ninject.Planning.Targets;
using Ninject.Selection;
using Ninject.Selection.Heuristics;
using Ninject.Syntax;

namespace Gigya.Microdot.Orleans.Ninject.Host.NinjectOrleansBinding
{
    /// <summary>
    /// Hold direct reference to all ServiceProvider Scope decencies and mange there life time.
    /// /// </summary>
    internal class ScopeCache : IDisposable
    {
        private ImmutableDictionary<Type, object> _scopeServices;
        private List<IDisposable> _disposables;
        private readonly object _locker = new object();
        private int _isDispose = 0;
        public ScopeCache()
        {
            _scopeServices = ImmutableDictionary.CreateBuilder<Type, object>().ToImmutable();
            _disposables = new List<IDisposable>();
        }

        public void Dispose()
        {
            // Should not lock to avoid deadlock
            // UseCase: When worker thread is during resolve during Kernel dispose
            if (Interlocked.CompareExchange(ref _isDispose, 1, 0) == 0)
            {

                foreach (var disposable in _disposables)
                {
                    disposable.Dispose();
                }
                _disposables = null;
                _scopeServices = null;
            }

        }

        public object GetOrCreate(Type key, Func<object> instancefactory)
        {
            var scopeService = _scopeServices;
            if (scopeService == null)
            {
                throw new ObjectDisposedException("cacheItem");
            }

            // The assumption that you create few object on scope but resolve the many time
            // scopeService mast be safe thread object !!(Out side the lock)
            if (scopeService.TryGetValue(key, out var result))
            {
                return result;
            }

            lock (_locker)
            {
                if (_scopeServices == null)
                {
                    throw new ObjectDisposedException("cacheItem");
                }

                if (_scopeServices.TryGetValue(key, out result))
                {
                    return result;
                }

                var instance = instancefactory();
                _scopeServices = _scopeServices.Add(key, instance);
                if (instance is IDisposable disposable)
                {
                    _disposables?.Add(disposable);
                }

                // Optimistic lock regarding the dispose
                // Don't need to use interlock inside lock
                if (_isDispose == 1)
                {
                    // Skipping dispose of the race condition instance in case it IDisposable
                    // In order to keep the code simple and not doing it inside the lock
                    _scopeServices = null;
                    _disposables = null;
                    throw new ObjectDisposedException("cacheItem");
                }

                return instance;
            }
        }
    }
}