├── .cirrus.yml ├── .cirrus └── Dockerfile ├── .git-blame-ignore-revs ├── .github ├── dependabot.yml ├── release.yml └── workflows │ ├── ci.yml │ └── clean.yml ├── .gitignore ├── .jvmopts ├── .mergify.yml ├── .scalafix.conf ├── .scalafmt.conf ├── CONTRIBUTING.md ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── RELEASING.md ├── benchmarks └── src │ └── main │ └── scala │ └── cats │ └── effect │ └── benchmarks │ ├── ArrayStackBenchmark.scala │ ├── AsyncBenchmark.scala │ ├── AtomicCellBenchmark.scala │ ├── AttemptBenchmark.scala │ ├── BlockingBenchmark.scala │ ├── BothBenchmark.scala │ ├── DeepBindBenchmark.scala │ ├── DeferredBenchmark.scala │ ├── DispatcherBenchmark.scala │ ├── HandleErrorBenchmark.scala │ ├── MapCallsBenchmark.scala │ ├── MapStreamBenchmark.scala │ ├── MutexBenchmark.scala │ ├── ParallelBenchmark.scala │ ├── QueueBenchmark.scala │ ├── RaceBenchmark.scala │ ├── RandomBenchmark.scala │ ├── RedeemBenchmark.scala │ ├── RedeemWithBenchmark.scala │ ├── RefBenchmark.scala │ ├── ScalQueueBenchmark.scala │ ├── ShallowBindBenchmark.scala │ ├── SleepBenchmark.scala │ ├── SleepDrift.scala │ ├── ThreadLocalBenchmark.scala │ └── WorkStealingBenchmark.scala ├── build.sbt ├── core ├── js-native │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ ├── IOFiberConstants.scala │ │ ├── IOLocalPlatform.scala │ │ └── SyncIOConstants.scala ├── js │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ ├── ArrayStack.scala │ │ ├── ByteStack.scala │ │ ├── CallbackStack.scala │ │ ├── CpuStarvationCheckPlatform.scala │ │ ├── IOApp.scala │ │ ├── IOCompanionPlatform.scala │ │ ├── IOFiberPlatform.scala │ │ ├── IOPlatform.scala │ │ ├── Platform.scala │ │ ├── SyncIOCompanionPlatform.scala │ │ ├── process.scala │ │ ├── syntax │ │ └── DispatcherSyntax.scala │ │ ├── tracing │ │ ├── TracingConstants.scala │ │ └── TracingPlatform.scala │ │ └── unsafe │ │ ├── BatchingMacrotaskExecutor.scala │ │ ├── FiberMonitor.scala │ │ ├── IORuntimeBuilderPlatform.scala │ │ ├── IORuntimeCompanionPlatform.scala │ │ ├── IORuntimeConfigCompanionPlatform.scala │ │ ├── JSArrayQueue.scala │ │ ├── SchedulerCompanionPlatform.scala │ │ ├── WorkStealingThreadPool.scala │ │ ├── metrics │ │ ├── IORuntimeMetricsCompanionPlatform.scala │ │ └── IORuntimeMetricsPlatform.scala │ │ └── ref │ │ ├── Reference.scala │ │ ├── ReferenceQueue.scala │ │ └── WeakReference.scala ├── jvm-native │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ ├── ArrayStack.scala │ │ ├── ByteStack.scala │ │ ├── CallbackStack.scala │ │ ├── CpuStarvationCheckPlatform.scala │ │ ├── IOCompanionMultithreadedPlatform.scala │ │ ├── IOFiberPlatform.scala │ │ ├── IOPlatform.scala │ │ ├── PlatformStatics.scala │ │ ├── SyncIOCompanionPlatform.scala │ │ ├── syntax │ │ └── DispatcherSyntax.scala │ │ └── unsafe │ │ ├── BatchingMacrotaskExecutor.scala │ │ ├── FiberMonitor.scala │ │ ├── LocalQueue.scala │ │ ├── PollingSystem.scala │ │ ├── ScalQueue.scala │ │ ├── SchedulerCompanionPlatform.scala │ │ ├── SleepSystem.scala │ │ ├── TimerHeap.scala │ │ ├── WorkStealingThreadPool.scala │ │ ├── WorkerThread.scala │ │ ├── metrics │ │ ├── IORuntimeMetricsCompanionPlatform.scala │ │ ├── IORuntimeMetricsPlatform.scala │ │ ├── PollerMetrics.scala │ │ └── WorkStealingThreadPoolMetrics.scala │ │ └── ref │ │ └── package.scala ├── jvm │ └── src │ │ └── main │ │ ├── java │ │ └── cats │ │ │ └── effect │ │ │ ├── IOFiberConstants.java │ │ │ ├── Signal.java │ │ │ ├── SyncIOConstants.java │ │ │ ├── tracing │ │ │ └── TracingConstants.java │ │ │ └── unsafe │ │ │ ├── LocalQueue.java │ │ │ ├── LocalQueueConstants.java │ │ │ └── WorkStealingThreadPoolConstants.java │ │ ├── resources │ │ └── META-INF │ │ │ └── native-image │ │ │ └── org.typelevel │ │ │ └── cats-effect │ │ │ ├── native-image.properties │ │ │ └── sun-misc-signal-proxy-config.json │ │ └── scala │ │ └── cats │ │ └── effect │ │ ├── IOApp.scala │ │ ├── IOCompanionPlatform.scala │ │ ├── IOLocalPlatform.scala │ │ ├── InterruptThrowable.scala │ │ ├── NonDaemonThreadLogger.scala │ │ ├── Platform.scala │ │ ├── Selector.scala │ │ ├── metrics │ │ └── JvmCpuStarvationMetrics.scala │ │ ├── tracing │ │ └── TracingPlatform.scala │ │ └── unsafe │ │ ├── IORuntimeBuilderPlatform.scala │ │ ├── IORuntimeCompanionPlatform.scala │ │ ├── IORuntimeConfigCompanionPlatform.scala │ │ ├── SelectorSystem.scala │ │ ├── WorkStealingThreadPoolPlatform.scala │ │ └── metrics │ │ ├── ComputePoolSampler.scala │ │ ├── ComputePoolSamplerMBean.scala │ │ ├── CpuStarvation.scala │ │ ├── CpuStarvationMBean.scala │ │ ├── LiveFiberSnapshotTrigger.scala │ │ ├── LiveFiberSnapshotTriggerMBean.scala │ │ ├── LocalQueueSampler.scala │ │ ├── LocalQueueSamplerMBean.scala │ │ ├── PollerSampler.scala │ │ ├── PollerSamplerMBean.scala │ │ ├── TimerHeapSampler.scala │ │ ├── TimerHeapSamplerMBean.scala │ │ ├── WorkerThreadSampler.scala │ │ └── WorkerThreadSamplerMBean.scala ├── native │ └── src │ │ └── main │ │ ├── resources │ │ └── scala-native │ │ │ └── signal_helper.c │ │ └── scala │ │ └── cats │ │ └── effect │ │ ├── FileDescriptorPoller.scala │ │ ├── IOApp.scala │ │ ├── IOCompanionPlatform.scala │ │ ├── InterruptThrowable.scala │ │ ├── Platform.scala │ │ ├── Signal.scala │ │ ├── tracing │ │ ├── TracingConstants.scala │ │ └── TracingPlatform.scala │ │ └── unsafe │ │ ├── EpollSystem.scala │ │ ├── IORuntimeBuilderPlatform.scala │ │ ├── IORuntimeCompanionPlatform.scala │ │ ├── IORuntimeConfigCompanionPlatform.scala │ │ ├── KqueueSystem.scala │ │ ├── LocalQueueConstants.scala │ │ ├── LocalQueuePadding.scala │ │ ├── WorkStealingThreadPoolConstants.scala │ │ └── WorkStealingThreadPoolPlatform.scala └── shared │ └── src │ └── main │ └── scala │ └── cats │ └── effect │ ├── ContState.scala │ ├── CpuStarvationCheck.scala │ ├── ExitCode.scala │ ├── IO.scala │ ├── IODeferred.scala │ ├── IOFiber.scala │ ├── IOLocal.scala │ ├── LiftIO.scala │ ├── ResourceApp.scala │ ├── SyncIO.scala │ ├── Trace.scala │ ├── implicits.scala │ ├── instances │ ├── AllInstances.scala │ └── package.scala │ ├── metrics │ └── CpuStarvationWarningMetrics.scala │ ├── package.scala │ ├── syntax │ ├── AllSyntax.scala │ └── package.scala │ ├── tracing │ ├── RingBuffer.scala │ ├── Tracing.scala │ └── TracingEvent.scala │ └── unsafe │ ├── FiberMonitorShared.scala │ ├── IORuntime.scala │ ├── IORuntimeBuilder.scala │ ├── IORuntimeConfig.scala │ ├── Scheduler.scala │ ├── StripedHashtable.scala │ ├── ThreadSafeHashtable.scala │ ├── UnsafeNonFatal.scala │ ├── WeakBag.scala │ ├── WeakList.scala │ ├── implicits.scala │ └── metrics │ ├── CpuStarvationMetrics.scala │ ├── CpuStarvationSampler.scala │ └── IORuntimeMetrics.scala ├── docs ├── assets │ ├── dispatcher.jpeg │ ├── hierarchy-impure.jpeg │ └── semaphore.png ├── concepts.md ├── core │ ├── fiber-dumps.md │ ├── io-local.md │ ├── io-runtime-config.md │ ├── jlink.md │ ├── native-image.md │ ├── scala-native.md │ ├── starvation-and-tuning.md │ └── test-runtime.md ├── faq.md ├── getting-started.md ├── migration-guide.md ├── recipes.md ├── schedulers.md ├── std │ ├── async-await.md │ ├── atomic-cell.md │ ├── backpressure.md │ ├── console.md │ ├── countdown-latch.md │ ├── cyclic-barrier.md │ ├── deferred.md │ ├── dequeue.md │ ├── dispatcher.md │ ├── env.md │ ├── hotswap.md │ ├── mapref.md │ ├── mutex.md │ ├── pqueue.md │ ├── queue.md │ ├── random.md │ ├── ref.md │ ├── resource.md │ ├── semaphore.md │ └── supervisor.md ├── third-party-resources.md ├── thread-model.md ├── tracing.md ├── tutorial.md ├── typeclasses.md └── typeclasses │ ├── async.md │ ├── clock.md │ ├── concurrent.md │ ├── monadcancel.md │ ├── spawn.md │ ├── sync.md │ ├── temporal.md │ └── unique.md ├── example ├── js │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── example │ │ └── Example.scala ├── jvm │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── example │ │ └── Example.scala ├── native │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── example │ │ └── Example.scala ├── test-js.sh ├── test-jvm.sh └── test-native.sh ├── flake.lock ├── flake.nix ├── graalvm-example └── src │ └── main │ └── scala │ └── cats │ └── effect │ └── example │ └── Example.scala ├── images ├── cats-effect-logo.png ├── contention.png └── hierarchy.svg ├── ioapp-tests └── src │ └── test │ └── scala │ └── IOAppSuite.scala ├── kernel-testkit └── shared │ └── src │ └── main │ └── scala │ └── cats │ └── effect │ └── kernel │ └── testkit │ ├── FreeSyncGenerators.scala │ ├── Generators.scala │ ├── PureConcGenerators.scala │ ├── TestContext.scala │ ├── TestInstances.scala │ ├── TimeT.scala │ ├── freeEval.scala │ ├── package.scala │ └── pure.scala ├── kernel ├── js │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── kernel │ │ ├── AsyncPlatform.scala │ │ ├── ClockPlatform.scala │ │ ├── ResourcePlatform.scala │ │ └── SyncRef.scala ├── jvm-native │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── kernel │ │ ├── ClockPlatform.scala │ │ └── SyncRef.scala ├── jvm │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── kernel │ │ ├── AsyncPlatform.scala │ │ └── ResourcePlatform.scala ├── native │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── kernel │ │ ├── AsyncPlatform.scala │ │ └── ResourcePlatform.scala └── shared │ └── src │ ├── main │ ├── scala-2.12 │ │ └── cats │ │ │ └── effect │ │ │ └── kernel │ │ │ └── syntax │ │ │ └── GenTemporalSyntaxCompat.scala │ ├── scala-2.13 │ │ └── cats │ │ │ └── effect │ │ │ └── kernel │ │ │ └── syntax │ │ │ └── GenTemporalSyntaxCompat.scala │ ├── scala-3 │ │ └── cats │ │ │ └── effect │ │ │ └── kernel │ │ │ └── syntax │ │ │ └── GenTemporalSyntaxCompat.scala │ └── scala │ │ └── cats │ │ └── effect │ │ └── kernel │ │ ├── Async.scala │ │ ├── CancelScope.scala │ │ ├── Clock.scala │ │ ├── Cont.scala │ │ ├── Deferred.scala │ │ ├── Fiber.scala │ │ ├── GenConcurrent.scala │ │ ├── GenSpawn.scala │ │ ├── GenTemporal.scala │ │ ├── MiniSemaphore.scala │ │ ├── MonadCancel.scala │ │ ├── Outcome.scala │ │ ├── ParallelF.scala │ │ ├── Poll.scala │ │ ├── Ref.scala │ │ ├── Resource.scala │ │ ├── Sync.scala │ │ ├── Unique.scala │ │ ├── implicits.scala │ │ ├── instances │ │ ├── AllInstances.scala │ │ ├── GenSpawnInstances.scala │ │ └── package.scala │ │ ├── package.scala │ │ └── syntax │ │ ├── AllSyntax.scala │ │ ├── AsyncSyntax.scala │ │ ├── ClockSyntax.scala │ │ ├── GenConcurrentSyntax.scala │ │ ├── GenSpawnSyntax.scala │ │ ├── GenTemporalSyntax.scala │ │ ├── MonadCancelSyntax.scala │ │ ├── ResourceSyntax.scala │ │ └── package.scala │ └── test │ └── scala │ └── cats │ └── effect │ └── kernel │ └── SyntaxSuite.scala ├── laws └── shared │ └── src │ ├── main │ └── scala │ │ └── cats │ │ └── effect │ │ └── laws │ │ ├── AsyncLaws.scala │ │ ├── AsyncTests.scala │ │ ├── ClockLaws.scala │ │ ├── ClockTests.scala │ │ ├── GenSpawnLaws.scala │ │ ├── GenSpawnTests.scala │ │ ├── GenTemporalLaws.scala │ │ ├── GenTemporalTests.scala │ │ ├── IsEq.scala │ │ ├── MonadCancelLaws.scala │ │ ├── MonadCancelTests.scala │ │ ├── SyncLaws.scala │ │ ├── SyncTests.scala │ │ ├── Tolerance.scala │ │ ├── UniqueLaws.scala │ │ ├── UniqueTests.scala │ │ └── package.scala │ └── test │ └── scala │ └── cats │ └── effect │ ├── BaseSuite.scala │ ├── kernel │ └── OutcomeSuite.scala │ ├── laws │ ├── ClockSuite.scala │ ├── EitherTFreeSyncSuite.scala │ ├── EitherTPureConcSuite.scala │ ├── FreeSyncSuite.scala │ ├── GenTemporalSuite.scala │ ├── IorTFreeSyncSuite.scala │ ├── IorTPureConcSuite.scala │ ├── KleisliFreeSyncSuite.scala │ ├── KleisliPureConcSuite.scala │ ├── OptionTFreeSyncSuite.scala │ ├── OptionTPureConcSuite.scala │ ├── PureConcSuite.scala │ ├── ReaderWriterStateTFreeSyncSuite.scala │ ├── ReaderWriterStateTPureConcSuite.scala │ ├── ResourcePureConcSuite.scala │ ├── StateTFreeSyncSuite.scala │ ├── StateTPureConcSuite.scala │ ├── WriterTFreeSyncSuite.scala │ └── WriterTPureConcSuite.scala │ └── testkit │ └── TimeTSuite.scala ├── package-lock.json ├── package.json ├── project ├── CI.scala ├── Common.scala ├── JSEnv.scala ├── build.properties └── plugins.sbt ├── scalafix ├── .scalafmt.conf ├── README.md ├── build.sbt ├── project │ ├── build.properties │ └── plugins.sbt ├── rules │ └── src │ │ └── main │ │ └── scala │ │ └── fix │ │ ├── v3_0_0.scala │ │ └── v3_3_0.scala ├── v3_0_0 │ ├── input │ │ └── src │ │ │ └── main │ │ │ └── scala │ │ │ └── fix │ │ │ ├── BlockerRewrites.scala │ │ │ ├── BracketRewrites.scala │ │ │ ├── ContextShiftRewrites.scala │ │ │ ├── IORewrites.scala │ │ │ ├── ParallelRewrites.scala │ │ │ ├── PkgRewrites.scala │ │ │ └── ResourceRewrites.scala │ ├── output │ │ └── src │ │ │ └── main │ │ │ └── scala │ │ │ └── fix │ │ │ ├── BlockerRewrites.scala │ │ │ ├── BracketRewrites.scala │ │ │ ├── ContextShiftRewrites.scala │ │ │ ├── IORewrites.scala │ │ │ ├── ParallelRewrites.scala │ │ │ ├── PkgRewrites.scala │ │ │ └── ResourceRewrites.scala │ └── tests │ │ └── src │ │ └── test │ │ └── scala │ │ └── fix │ │ └── CatsEffectTests.scala └── v3_3_0 │ ├── input │ └── src │ │ └── main │ │ └── scala │ │ └── fix │ │ └── InterruptibleRewrites.scala │ ├── output │ └── src │ │ └── main │ │ └── scala │ │ └── fix │ │ └── InterruptibleRewrites.scala │ └── tests │ └── src │ └── test │ └── scala │ └── fix │ └── CatsEffectTests.scala ├── scripts ├── data │ ├── scastie.sbt │ └── scastie.scala ├── make-release-prs.sh ├── make-site-pr.sh ├── post-release-discord.sh └── update-versions.sh ├── site-docs ├── sidebars-todo.json └── sidebars.json ├── std ├── js-native │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── std │ │ └── UUIDGenCompanionPlatform.scala ├── js │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── std │ │ ├── Console.scala │ │ ├── DispatcherPlatform.scala │ │ ├── EnvCompanionPlatform.scala │ │ ├── MapRefCompanionPlatform.scala │ │ └── SecureRandomCompanionPlatform.scala ├── jvm-native │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── std │ │ ├── Console.scala │ │ ├── DispatcherPlatform.scala │ │ ├── EnvCompanionPlatform.scala │ │ └── MapRefCompanionPlatform.scala ├── jvm │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── std │ │ ├── ConsoleCompanionPlatform.scala │ │ ├── SecureRandomCompanionPlatform.scala │ │ └── UUIDGenCompanionPlatform.scala ├── native │ └── src │ │ └── main │ │ └── scala │ │ └── cats │ │ └── effect │ │ └── std │ │ ├── ConsoleCompanionPlatform.scala │ │ └── SecureRandomCompanionPlatform.scala └── shared │ └── src │ ├── main │ └── scala │ │ └── cats │ │ └── effect │ │ └── std │ │ ├── AtomicCell.scala │ │ ├── Backpressure.scala │ │ ├── ConsoleCrossPlatform.scala │ │ ├── CountDownLatch.scala │ │ ├── CyclicBarrier.scala │ │ ├── Dequeue.scala │ │ ├── Dispatcher.scala │ │ ├── Env.scala │ │ ├── FailureSignal.scala │ │ ├── Hotswap.scala │ │ ├── MapRef.scala │ │ ├── Mutex.scala │ │ ├── PQueue.scala │ │ ├── Queue.scala │ │ ├── QueueSink.scala │ │ ├── QueueSource.scala │ │ ├── Random.scala │ │ ├── SecureRandom.scala │ │ ├── Semaphore.scala │ │ ├── Supervisor.scala │ │ ├── SystemProperties.scala │ │ ├── UUIDGen.scala │ │ ├── UnsafeUnbounded.scala │ │ ├── internal │ │ ├── BankersQueue.scala │ │ └── BinomialHeap.scala │ │ ├── syntax │ │ ├── AllSyntax.scala │ │ ├── BackpressureSyntax.scala │ │ ├── SupervisorSyntax.scala │ │ └── package.scala │ │ └── unsafe │ │ ├── BoundedQueue.scala │ │ ├── BoundedQueueSink.scala │ │ ├── UnboundedQueue.scala │ │ └── UnboundedQueueSink.scala │ └── test │ └── scala │ └── cats │ └── effect │ └── std │ └── SyntaxSuite.scala ├── testkit └── shared │ └── src │ └── main │ └── scala │ └── cats │ └── effect │ └── testkit │ ├── TestControl.scala │ ├── TestException.scala │ ├── TestInstances.scala │ └── package.scala └── tests ├── js └── src │ ├── main │ └── scala │ │ ├── cats │ │ └── effect │ │ │ └── DetectPlatform.scala │ │ └── catseffect │ │ └── examplesplatform.scala │ └── test │ └── scala │ └── cats │ └── effect │ ├── ContSpecBasePlatform.scala │ ├── IOPlatformSuite.scala │ ├── RunnersPlatform.scala │ ├── SyncIOPlatformSuite.scala │ ├── exports.scala │ ├── std │ └── ConsoleJSSuite.scala │ └── unsafe │ ├── BatchingMacrotaskExecutorSuite.scala │ ├── JSArrayQueueSuite.scala │ ├── SchedulerSuite.scala │ └── StripedHashtableSuite.scala ├── jvm-native └── src │ ├── main │ └── scala │ │ └── catseffect │ │ └── examplesjvmnative.scala │ └── test │ └── scala │ └── cats │ └── effect │ ├── ContSpecBasePlatform.scala │ ├── IOConcurrencySuite.scala │ ├── RunnersPlatform.scala │ ├── SyncIOPlatformSuite.scala │ └── std │ ├── DeferredParallelismSuite.scala │ └── DispatcherParallelSuite.scala ├── jvm └── src │ ├── main │ └── scala │ │ └── catseffect │ │ └── examplesplatform.scala │ └── test │ ├── resources │ ├── readline-test.ISO-8859-1.txt │ ├── readline-test.US-ASCII.txt │ ├── readline-test.UTF-16.txt │ ├── readline-test.UTF-16BE.txt │ ├── readline-test.UTF-16LE.txt │ └── readline-test.UTF-8.txt │ └── scala │ └── cats │ └── effect │ ├── DetectPlatform.scala │ ├── IOPlatformSuite.scala │ ├── ParasiticECSuite.scala │ ├── ResourceJVMSuite.scala │ ├── SelectorSuite.scala │ ├── kernel │ └── AsyncPlatformSuite.scala │ ├── std │ ├── ConsoleJVMSuite.scala │ └── MapRefJVMSuite.scala │ └── unsafe │ ├── BlockingStressSuite.scala │ ├── DrainBatchSuite.scala │ ├── FiberMonitorSuite.scala │ ├── HelperThreadParkSuite.scala │ ├── IOLocalsSuite.scala │ ├── SleepersSuite.scala │ ├── StripedHashtableSuite.scala │ ├── TimerHeapSuite.scala │ └── WorkerThreadNameSuite.scala ├── native └── src │ ├── main │ └── scala │ │ └── catseffect │ │ └── examplesplatform.scala │ └── test │ └── scala │ └── cats │ └── effect │ ├── DetectPlatform.scala │ ├── FileDescriptorPollerSuite.scala │ ├── IOPlatformSuite.scala │ └── unsafe │ └── SchedulerSuite.scala └── shared └── src ├── main └── scala │ └── catseffect │ ├── RawApp.scala │ └── examples.scala └── test ├── scala-2.13+ ├── cats │ └── effect │ │ └── IOImplicitSuite.scala └── not │ └── cats │ └── effect │ ├── IOCompilationSuite.scala │ └── IOParImplicitSuite.scala └── scala └── cats └── effect ├── BaseSuite.scala ├── CallbackStackSuite.scala ├── ContSuite.scala ├── EitherTIOSuite.scala ├── ExitCodeSuite.scala ├── IOFiberSuite.scala ├── IOLocalSuite.scala ├── IOMtlLocalSuite.scala ├── IOParSuite.scala ├── IOPropSuite.scala ├── IOSuite.scala ├── IorTIOSuite.scala ├── KleisliIOSuite.scala ├── MemoizeSuite.scala ├── OptionTIOSuite.scala ├── ResourceSuite.scala ├── Runners.scala ├── StateTIOSuite.scala ├── SyncIOSuite.scala ├── ThunkSuite.scala ├── WriterTIOSuite.scala ├── kernel ├── AsyncSuite.scala ├── DeferredSuite.scala ├── DerivationRefinementSuite.scala ├── LensRefSuite.scala ├── MiniSemaphoreSuite.scala ├── ParallelFSuite.scala └── RefSuite.scala ├── std ├── AtomicCellSuite.scala ├── BackpressureSuite.scala ├── ConsoleSuite.scala ├── CountDownLatchSuite.scala ├── CyclicBarrierSuite.scala ├── DequeueSuite.scala ├── DispatcherSuite.scala ├── EnvSuite.scala ├── HotswapSuite.scala ├── MapRefSuite.scala ├── MutexSuite.scala ├── PQueueSuite.scala ├── QueueSuite.scala ├── RandomSuite.scala ├── SecureRandomSuite.scala ├── SemaphoreSuite.scala ├── SupervisorSuite.scala ├── SystemPropertiesSuite.scala ├── UUIDGenSuite.scala ├── UnsafeBoundedSuite.scala ├── UnsafeUnboundedSuite.scala └── internal │ ├── BankersQueueSuite.scala │ └── BinomialHeapSuite.scala ├── testkit └── TestControlSuite.scala ├── tracing ├── TraceSuite.scala └── TracingSuite.scala └── unsafe ├── IORuntimeBuilderSuite.scala ├── IORuntimeConfigSuite.scala └── IORuntimeSuite.scala /.cirrus.yml: -------------------------------------------------------------------------------- 1 | jvm_highcore_task: 2 | only_if: $CIRRUS_TAG != '' || $CIRRUS_PR != '' 3 | required_pr_labels: Cirrus JVM 4 | container: 5 | image: sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.0_3.3.0 6 | cpu: 8 7 | memory: 16G 8 | matrix: 9 | - name: JVM high-core-count 2.13 10 | script: sbt '++ 2.13' testsJVM/test ioAppTestsJVM/test 11 | - name: JVM high-core-count 3 12 | script: sbt '++ 3' testsJVM/test ioAppTestsJVM/test 13 | 14 | native_highcore_task: 15 | only_if: $CIRRUS_TAG != '' || $CIRRUS_PR != '' 16 | required_pr_labels: Cirrus Native 17 | container: 18 | dockerfile: .cirrus/Dockerfile 19 | cpu: 8 20 | memory: 16G 21 | matrix: 22 | - name: Native high-core-count 2.13 23 | script: sbt '++ 2.13' testsNative/test ioAppTestsNative/test 24 | - name: Native high-core-count 3 25 | script: sbt '++ 3' testsNative/test ioAppTestsNative/test 26 | -------------------------------------------------------------------------------- /.cirrus/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.0_3.3.0 2 | 3 | RUN apt-get update && apt-get install -y clang 4 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Scala Steward: Reformat with scalafmt 3.5.9 2 | c3404c6577af33d65017aeaca248d51dab770021 3 | 4 | # Scala Steward: Reformat with scalafmt 3.7.1 5 | 52c851127a918b050f7b1d33ad71f128cb7bc48e 6 | 7 | # Scala Steward: Reformat with scalafmt 3.7.9 8 | db6c201aad98cc3d19f67cc688dfa6332e2fb939 9 | 10 | # Scala Steward: Reformat with scalafmt 3.8.4 11 | 97565e196071ba28bac911411b9c18bd0e6526e8 12 | 13 | # Revert documentation format changes 14 | ba11dfe5b6ab7c9f45521dde7c110212629ac50f 15 | 16 | # Scala Steward: Reformat with scalafmt 3.9.2 17 | 1481ec379267b5c6a79897bd43b61f02f4253ec3 18 | 19 | # Scala Steward: Reformat with scalafmt 3.9.3 20 | 9c149e8c387b368594545995f09cc8180964ae3a 21 | 22 | # Scala Steward: Reformat with scalafmt 3.9.4 23 | fa1afb9141016bf6f72896b9867a9bcba3cb2933 24 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gitsubmodule 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | target-branch: docs 9 | - package-ecosystem: docker 10 | directory: "/.cirrus" 11 | schedule: 12 | interval: weekly 13 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | categories: 3 | - title: Enhancements 4 | labels: 5 | - ':mushroom: enhancement' 6 | - title: Bug Fixes 7 | labels: 8 | - ':beetle: bug' 9 | - title: Documentation 10 | labels: 11 | - ':books: docs' 12 | - title: Behind the Scenes 13 | labels: 14 | - ':gear: infrastructure' 15 | - ':robot:' 16 | - ':art: backstage' 17 | # Not for published notes, just to make sure we don't forget any accidentally unlabeled PRs 18 | - title: Uncategorized 19 | labels: 20 | - '*' 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | 3 | .sbtopts 4 | 5 | # vim 6 | *.sw? 7 | 8 | # intellij 9 | .idea/ 10 | 11 | # Ignore [ce]tags files 12 | tags 13 | 14 | # Metals 15 | .metals/ 16 | .bsp/ 17 | .bloop/ 18 | metals.sbt 19 | .vscode 20 | 21 | # npm 22 | node_modules/ 23 | 24 | # nix flake 25 | .direnv/ 26 | -------------------------------------------------------------------------------- /.jvmopts: -------------------------------------------------------------------------------- 1 | -Xmx4G 2 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: label typelevel-steward's PRs 3 | conditions: 4 | - author=typelevel-steward[bot] 5 | actions: 6 | label: 7 | add: [':robot:'] 8 | - name: label typelevel-steward's update PRs 9 | conditions: 10 | - author=typelevel-steward[bot] 11 | - body~=labels:.*library-update 12 | actions: 13 | label: 14 | add: [dependencies] 15 | - name: label dependabots's PRs 16 | conditions: 17 | - author=dependabot[bot] 18 | actions: 19 | label: 20 | add: [':robot:'] 21 | - name: automatically merge dependabot docs PRs 22 | conditions: 23 | - author=dependabot[bot] 24 | - check-success=Generate Microsite 25 | - base=docs 26 | actions: 27 | merge: 28 | method: merge 29 | -------------------------------------------------------------------------------- /.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [OrganizeImports] 2 | 3 | OrganizeImports { 4 | groupedImports = Merge 5 | importsOrder = SymbolsFirst 6 | importSelectorsOrder = SymbolsFirst 7 | groups = [ 8 | "cats.", 9 | "coop.", 10 | "org.", 11 | "scala.", 12 | "java.", 13 | "javax.", 14 | "*" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | cats-effect 2 | Copyright 2020-2025 Typelevel 3 | Licensed under Apache License 2.0 (see LICENSE) 4 | 5 | This software contains portions of code derived from scala-js 6 | https://github.com/scala-js/scala-js 7 | Copyright EPFL 8 | Licensed under Apache License 2.0 (see LICENSE) 9 | -------------------------------------------------------------------------------- /core/js-native/src/main/scala/cats/effect/IOLocalPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | private[effect] trait IOLocalPlatform[A] 20 | -------------------------------------------------------------------------------- /core/js-native/src/main/scala/cats/effect/SyncIOConstants.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | private object SyncIOConstants { 20 | final val MaxStackDepth = 512 21 | 22 | final val MapK = 0 23 | final val FlatMapK = 1 24 | final val HandleErrorWithK = 2 25 | final val RunTerminusK = 3 26 | final val AttemptK = 4 27 | } 28 | -------------------------------------------------------------------------------- /core/js/src/main/scala/cats/effect/CpuStarvationCheckPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import scala.concurrent.duration.FiniteDuration 20 | import scala.scalajs.js 21 | 22 | private[effect] abstract class CpuStarvationCheckPlatform { this: CpuStarvationCheck.type => 23 | 24 | def format(when: FiniteDuration): String = 25 | new js.Date(when.toMillis.toDouble).toISOString() 26 | 27 | } 28 | -------------------------------------------------------------------------------- /core/js/src/main/scala/cats/effect/IOFiberPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import java.util.concurrent.atomic.AtomicBoolean 20 | 21 | private[effect] abstract class IOFiberPlatform[A] extends AtomicBoolean(false) { 22 | this: IOFiber[A] => 23 | 24 | // in theory this code should never be hit due to the override in IOCompanionPlatform 25 | def interruptibleImpl(cur: IO.Blocking[Any]): IO[Any] = IO(cur.thunk()) 26 | } 27 | -------------------------------------------------------------------------------- /core/js/src/main/scala/cats/effect/Platform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | private object Platform { 20 | final val isJs = true 21 | final val isJvm = false 22 | final val isNative = false 23 | 24 | class static extends scala.annotation.Annotation 25 | final class volatileNative extends scala.annotation.Annotation 26 | } 27 | -------------------------------------------------------------------------------- /core/js/src/main/scala/cats/effect/SyncIOCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import scala.scalajs.js 20 | 21 | private[effect] trait SyncIOCompanionPlatform { this: SyncIO.type => 22 | final def realTimeDate: SyncIO[js.Date] = realTime.map(d => new js.Date(d.toMillis.toDouble)) 23 | } 24 | -------------------------------------------------------------------------------- /core/js/src/main/scala/cats/effect/process.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import cats.data.OptionT 20 | import cats.effect.std.Env 21 | 22 | import scala.scalajs.js 23 | import scala.util.Try 24 | 25 | private[effect] object process { 26 | 27 | def argv: Option[List[String]] = Try( 28 | js.Dynamic.global.process.argv.asInstanceOf[js.Array[String]].toList.drop(2)).toOption 29 | 30 | def env(key: String): Option[String] = { 31 | val env = Env.make[SyncIO] 32 | OptionT(env.get(key)).orElseF(env.get(s"REACT_APP_$key")).value.unsafeRunSync() 33 | } 34 | 35 | def on(eventName: String, listener: js.Function0[Unit]): Unit = 36 | Try(js.Dynamic.global.process.on(eventName, listener).asInstanceOf[Unit]).recover { 37 | case _ => () // Silently ignore failure 38 | }.get 39 | } 40 | -------------------------------------------------------------------------------- /core/js/src/main/scala/cats/effect/tracing/TracingConstants.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package tracing 19 | 20 | import scala.scalajs.js 21 | 22 | private[effect] object TracingConstants { 23 | 24 | private[this] final val stackTracingMode: String = 25 | process.env("CATS_EFFECT_TRACING_MODE").filterNot(_.isEmpty).getOrElse { 26 | if (js.typeOf(js.Dynamic.global.process) != "undefined" 27 | && js.typeOf(js.Dynamic.global.process.release) != "undefined" 28 | && js.Dynamic.global.process.release.name == "node".asInstanceOf[js.Any]) 29 | "cached" 30 | else 31 | "none" 32 | } 33 | 34 | final val isCachedStackTracing: Boolean = stackTracingMode.equalsIgnoreCase("cached") 35 | 36 | final val isFullStackTracing: Boolean = stackTracingMode.equalsIgnoreCase("full") 37 | 38 | final val isStackTracing: Boolean = isFullStackTracing || isCachedStackTracing 39 | } 40 | -------------------------------------------------------------------------------- /core/js/src/main/scala/cats/effect/unsafe/metrics/IORuntimeMetricsCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe.metrics 18 | 19 | import scala.concurrent.ExecutionContext 20 | 21 | private[metrics] abstract class IORuntimeMetricsCompanionPlatform { 22 | this: IORuntimeMetrics.type => 23 | 24 | private[unsafe] def apply(ec: ExecutionContext): IORuntimeMetrics = { 25 | val _ = ec 26 | new IORuntimeMetrics { 27 | private[effect] val cpuStarvationSampler: CpuStarvationSampler = 28 | CpuStarvationSampler() 29 | 30 | val cpuStarvation: CpuStarvationMetrics = 31 | CpuStarvationMetrics(cpuStarvationSampler) 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /core/js/src/main/scala/cats/effect/unsafe/metrics/IORuntimeMetricsPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe.metrics 18 | 19 | private[metrics] trait IORuntimeMetricsPlatform { this: IORuntimeMetrics => } 20 | -------------------------------------------------------------------------------- /core/js/src/main/scala/cats/effect/unsafe/ref/WeakReference.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * scalajs-weakreferences (https://github.com/scala-js/scala-js-weakreferences) 19 | * 20 | * Copyright EPFL. 21 | * 22 | * Licensed under Apache License 2.0 23 | * (https://www.apache.org/licenses/LICENSE-2.0). 24 | * 25 | * See the NOTICE file distributed with this work for 26 | * additional information regarding copyright ownership. 27 | */ 28 | 29 | package cats.effect.unsafe.ref 30 | 31 | private[unsafe] class WeakReference[T](referent: T, q: ReferenceQueue[? >: T]) 32 | extends Reference[T](referent, q) { 33 | 34 | def this(referent: T) = this(referent, null) 35 | } 36 | -------------------------------------------------------------------------------- /core/jvm-native/src/main/scala/cats/effect/CpuStarvationCheckPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import scala.concurrent.duration.FiniteDuration 20 | 21 | import java.time.Instant 22 | import java.time.format.DateTimeFormatter 23 | 24 | private[effect] abstract class CpuStarvationCheckPlatform { this: CpuStarvationCheck.type => 25 | 26 | def format(when: FiniteDuration): String = 27 | DateTimeFormatter.ISO_INSTANT.format(Instant.ofEpochMilli(when.toMillis)) 28 | 29 | } 30 | -------------------------------------------------------------------------------- /core/jvm-native/src/main/scala/cats/effect/PlatformStatics.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | // copy from scala.runtime.PStatics 20 | private[effect] object PlatformStatics { 21 | // `Int.MaxValue - 8` traditional soft limit to maximize compatibility with diverse JVMs 22 | // See https://stackoverflow.com/a/8381338 for example 23 | final val VM_MaxArraySize = 2147483639 24 | } 25 | -------------------------------------------------------------------------------- /core/jvm-native/src/main/scala/cats/effect/SyncIOCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import java.time.Instant 20 | 21 | private[effect] trait SyncIOCompanionPlatform { this: SyncIO.type => 22 | final def realTimeInstant: SyncIO[Instant] = 23 | realTime.map(d => Instant.ofEpochMilli(d.toMillis)) 24 | } 25 | -------------------------------------------------------------------------------- /core/jvm-native/src/main/scala/cats/effect/syntax/DispatcherSyntax.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.syntax 18 | 19 | trait DispatcherSyntax 20 | -------------------------------------------------------------------------------- /core/jvm-native/src/main/scala/cats/effect/unsafe/BatchingMacrotaskExecutor.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package unsafe 19 | 20 | import scala.concurrent.ExecutionContext 21 | 22 | private[effect] sealed abstract class BatchingMacrotaskExecutor private () 23 | extends ExecutionContext { 24 | def schedule(runnable: Runnable): Unit 25 | } 26 | -------------------------------------------------------------------------------- /core/jvm-native/src/main/scala/cats/effect/unsafe/metrics/IORuntimeMetricsCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe.metrics 18 | 19 | import scala.concurrent.ExecutionContext 20 | 21 | private[metrics] abstract class IORuntimeMetricsCompanionPlatform { 22 | this: IORuntimeMetrics.type => 23 | 24 | private[unsafe] def apply(ec: ExecutionContext): IORuntimeMetrics = 25 | new IORuntimeMetrics { 26 | private[effect] val cpuStarvationSampler: CpuStarvationSampler = 27 | CpuStarvationSampler() 28 | 29 | val cpuStarvation: CpuStarvationMetrics = 30 | CpuStarvationMetrics(cpuStarvationSampler) 31 | 32 | val workStealingThreadPool: Option[WorkStealingThreadPoolMetrics] = 33 | WorkStealingThreadPoolMetrics(ec) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /core/jvm-native/src/main/scala/cats/effect/unsafe/metrics/IORuntimeMetricsPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe.metrics 18 | 19 | private[metrics] trait IORuntimeMetricsPlatform { this: IORuntimeMetrics => 20 | 21 | /** 22 | * Returns work-stealing thread pool metrics. 23 | * 24 | * @example 25 | * {{{ 26 | * val runtime: IORuntime = ??? 27 | * val totalWorkers = runtime.metrics.workStealingThreadPool.map(_.compute.workerThreadCount()) 28 | * }}} 29 | */ 30 | def workStealingThreadPool: Option[WorkStealingThreadPoolMetrics] 31 | } 32 | -------------------------------------------------------------------------------- /core/jvm-native/src/main/scala/cats/effect/unsafe/ref/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe 18 | 19 | package object ref { 20 | private[unsafe] type Reference[A] = java.lang.ref.Reference[A] 21 | private[unsafe] type ReferenceQueue[A] = java.lang.ref.ReferenceQueue[A] 22 | private[unsafe] type WeakReference[A] = java.lang.ref.WeakReference[A] 23 | } 24 | -------------------------------------------------------------------------------- /core/jvm/src/main/java/cats/effect/SyncIOConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect; 18 | 19 | final class SyncIOConstants { 20 | 21 | public static final int MaxStackDepth = 512; 22 | 23 | public static final byte MapK = 0; 24 | public static final byte FlatMapK = 1; 25 | public static final byte HandleErrorWithK = 2; 26 | public static final byte RunTerminusK = 3; 27 | public static final byte AttemptK = 4; 28 | } 29 | -------------------------------------------------------------------------------- /core/jvm/src/main/resources/META-INF/native-image/org.typelevel/cats-effect/native-image.properties: -------------------------------------------------------------------------------- 1 | Args = -H:DynamicProxyConfigurationResources=${.}/sun-misc-signal-proxy-config.json 2 | -------------------------------------------------------------------------------- /core/jvm/src/main/resources/META-INF/native-image/org.typelevel/cats-effect/sun-misc-signal-proxy-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "interfaces": [ "sun.misc.SignalHandler" ] } 3 | ] 4 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/IOCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import java.util.concurrent.{CompletableFuture, CompletionStage} 20 | 21 | private[effect] abstract class IOCompanionPlatform extends IOCompanionMultithreadedPlatform { 22 | this: IO.type => 23 | 24 | def fromCompletableFuture[A](fut: IO[CompletableFuture[A]]): IO[A] = 25 | asyncForIO.fromCompletableFuture(fut) 26 | 27 | def fromCompletionStage[A](completionStage: IO[CompletionStage[A]]): IO[A] = 28 | asyncForIO.fromCompletionStage(completionStage) 29 | } 30 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/InterruptThrowable.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import java.nio.channels.ClosedByInterruptException 20 | 21 | private[effect] object InterruptThrowable { 22 | def apply(t: Throwable): Boolean = t match { 23 | case _: InterruptedException => true 24 | case _: ClosedByInterruptException => true 25 | case _ => false 26 | } 27 | 28 | def ClosedByInterrupt(t: Throwable): Boolean = t match { 29 | case _: ClosedByInterruptException => true 30 | case _ => false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/Platform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | private object Platform { 20 | final val isJs = false 21 | final val isJvm = true 22 | final val isNative = false 23 | 24 | type static = org.typelevel.scalaccompat.annotation.static3 25 | final class safePublish extends scala.annotation.Annotation 26 | final class volatileNative extends scala.annotation.Annotation 27 | } 28 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/Selector.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import cats.syntax.all._ 20 | 21 | import java.nio.channels.SelectableChannel 22 | import java.nio.channels.spi.SelectorProvider 23 | 24 | trait Selector { 25 | 26 | /** 27 | * The [[java.nio.channels.spi.SelectorProvider]] that should be used to create 28 | * [[java.nio.channels.SelectableChannel]]s that are compatible with this polling system. 29 | */ 30 | def provider: SelectorProvider 31 | 32 | /** 33 | * Fiber-block until a [[java.nio.channels.SelectableChannel]] is ready on at least one of the 34 | * designated operations. The returned value will indicate which operations are ready. 35 | */ 36 | def select(ch: SelectableChannel, ops: Int): IO[Int] 37 | 38 | } 39 | 40 | object Selector { 41 | def find: IO[Option[Selector]] = 42 | IO.pollers.map(_.collectFirst { case selector: Selector => selector }) 43 | 44 | def get = find.flatMap( 45 | _.liftTo[IO](new RuntimeException("No Selector installed in this IORuntime")) 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/unsafe/WorkStealingThreadPoolPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package unsafe 19 | 20 | import java.time.Instant 21 | import java.time.temporal.ChronoField 22 | 23 | trait WorkStealingThreadPoolPlatform[P <: AnyRef] extends Scheduler { 24 | this: WorkStealingThreadPool[P] => 25 | 26 | override def nowMicros(): Long = { 27 | val now = Instant.now() 28 | now.getEpochSecond() * 1000000 + now.getLong(ChronoField.MICRO_OF_SECOND) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/unsafe/metrics/ComputePoolSampler.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe 18 | package metrics 19 | 20 | /** 21 | * An implementation of the [[ComputePoolSamplerMBean]] interface which simply delegates to the 22 | * corresponding methods of the [[cats.effect.unsafe.WorkStealingThreadPool]] being monitored. 23 | * 24 | * @param compute 25 | * the monitored compute work stealing thread pool 26 | */ 27 | private[unsafe] final class ComputePoolSampler(compute: WorkStealingThreadPool[?]) 28 | extends ComputePoolSamplerMBean { 29 | def getWorkerThreadCount(): Int = compute.getWorkerThreadCount() 30 | def getActiveThreadCount(): Int = compute.getActiveThreadCount() 31 | def getSearchingThreadCount(): Int = compute.getSearchingThreadCount() 32 | def getBlockedWorkerThreadCount(): Int = compute.getBlockedWorkerThreadCount() 33 | def getLocalQueueFiberCount(): Long = compute.getLocalQueueFiberCount() 34 | def getSuspendedFiberCount(): Long = compute.getSuspendedFiberCount() 35 | } 36 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/unsafe/metrics/CpuStarvation.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe.metrics 18 | 19 | private[effect] final class CpuStarvation( 20 | sampler: CpuStarvationSampler 21 | ) extends CpuStarvationMBean { 22 | 23 | def getCpuStarvationCount(): Long = 24 | sampler.cpuStarvationCount() 25 | 26 | def getMaxClockDriftMs(): Long = 27 | sampler.clockDriftMaxMs() 28 | 29 | def getCurrentClockDriftMs(): Long = 30 | sampler.clockDriftCurrentMs() 31 | } 32 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/unsafe/metrics/CpuStarvationMBean.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe.metrics 18 | 19 | /** 20 | * An MBean interfaces for monitoring when CPU starvation occurs. 21 | */ 22 | private[unsafe] trait CpuStarvationMBean { 23 | 24 | /** 25 | * Returns the number of times CPU starvation has occurred. 26 | * 27 | * @return 28 | * count of the number of times CPU starvation has occurred. 29 | */ 30 | def getCpuStarvationCount(): Long 31 | 32 | /** 33 | * Tracks the maximum clock seen during runtime. 34 | * 35 | * @return 36 | * the current maximum clock drift observed in milliseconds. 37 | */ 38 | def getMaxClockDriftMs(): Long 39 | 40 | /** 41 | * Tracks the current clock drift. 42 | * 43 | * @return 44 | * the current clock drift in milliseconds. 45 | */ 46 | def getCurrentClockDriftMs(): Long 47 | } 48 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/unsafe/metrics/LiveFiberSnapshotTrigger.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe 18 | package metrics 19 | 20 | import scala.collection.mutable.ArrayBuffer 21 | 22 | import java.util.concurrent.atomic.AtomicLong 23 | 24 | /** 25 | * An implementation of the [[LiveFiberSnapshotTriggerMBean]] interface which simply delegates 26 | * to the corresponding method of the backing [[cats.effect.unsafe.FiberMonitor]]. 27 | * 28 | * @param monitor 29 | * the backing fiber monitor 30 | */ 31 | private[unsafe] final class LiveFiberSnapshotTrigger(monitor: FiberMonitor) 32 | extends LiveFiberSnapshotTriggerMBean { 33 | def liveFiberSnapshot(): Array[String] = { 34 | val buffer = new ArrayBuffer[String] 35 | monitor.liveFiberSnapshot(buffer += _) 36 | buffer.toArray 37 | } 38 | } 39 | 40 | private[unsafe] object LiveFiberSnapshotTrigger { 41 | val IdCounter: AtomicLong = new AtomicLong(0) 42 | } 43 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/unsafe/metrics/LiveFiberSnapshotTriggerMBean.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe.metrics 18 | 19 | /** 20 | * An MBean interface for triggering live fiber snapshots. 21 | */ 22 | private[unsafe] trait LiveFiberSnapshotTriggerMBean { 23 | 24 | /** 25 | * Obtains a snapshot of the fibers currently live on the [[IORuntime]] which this fiber 26 | * monitor instance belongs to. 27 | * 28 | * @return 29 | * a textual representation of the runtime snapshot, `null` if a snapshot cannot be obtained 30 | */ 31 | def liveFiberSnapshot(): Array[String] 32 | } 33 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/unsafe/metrics/TimerHeapSampler.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe 18 | package metrics 19 | 20 | /** 21 | * An implementation of the [[TimerHeapSamplerMBean]] interface which simply delegates to the 22 | * corresponding methods of the [[cats.effect.unsafe.TimerHeap]] being monitored. 23 | * 24 | * @param timer 25 | * the monitored timer heap 26 | */ 27 | private[unsafe] final class TimerHeapSampler(timer: TimerHeap) extends TimerHeapSamplerMBean { 28 | def getTimersOutstandingCount(): Int = timer.outstandingTimers() 29 | def getTotalTimersExecutedCount(): Long = timer.totalTimersExecuted() 30 | def getTotalTimersScheduledCount(): Long = timer.totalTimersScheduled() 31 | def getTotalTimersCanceledCount(): Long = timer.totalTimersCanceled() 32 | def getNextTimerDue(): Long = timer.nextTimerDue().getOrElse(0L) 33 | def getPackCount(): Long = timer.packCount() 34 | } 35 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/unsafe/metrics/WorkerThreadSampler.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe 18 | package metrics 19 | 20 | /** 21 | * An implementation of the [[WorkerThreadSamplerMBean]] interface which simply delegates to the 22 | * corresponding methods of the [[cats.effect.unsafe.WorkerThread]] being monitored. 23 | * 24 | * @param thread 25 | * the monitored thread 26 | */ 27 | private[unsafe] final class WorkerThreadSampler(thread: WorkerThread.Metrics) 28 | extends WorkerThreadSamplerMBean { 29 | def getIdleTime(): Long = thread.getIdleTime() 30 | def getParkedCount(): Long = thread.getParkedCount() 31 | def getPolledCount(): Long = thread.getPolledCount() 32 | def getBlockingCount(): Long = thread.getBlockingCount() 33 | def getRespawnCount(): Long = thread.getRespawnCount() 34 | } 35 | -------------------------------------------------------------------------------- /core/jvm/src/main/scala/cats/effect/unsafe/metrics/WorkerThreadSamplerMBean.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe.metrics 18 | 19 | /** 20 | * An MBean interface for monitoring a single [[WorkerThread]]. 21 | */ 22 | private[unsafe] trait WorkerThreadSamplerMBean { 23 | 24 | /** 25 | * The total amount of time in nanoseconds that this WorkerThread has been parked. 26 | */ 27 | def getIdleTime(): Long 28 | 29 | /** 30 | * The total number of times that this WorkerThread has parked. 31 | */ 32 | def getParkedCount(): Long 33 | 34 | /** 35 | * The total number of times that this WorkerThread has polled for I/O events. 36 | */ 37 | def getPolledCount(): Long 38 | 39 | /** 40 | * The total number of times that this WorkerThread has switched to a blocking thread and been 41 | * replaced. 42 | */ 43 | def getBlockingCount(): Long 44 | 45 | /** 46 | * The total number of times that this WorkerThread has been replaced by a newly spawned 47 | * thread. 48 | */ 49 | def getRespawnCount(): Long 50 | 51 | } 52 | -------------------------------------------------------------------------------- /core/native/src/main/resources/scala-native/signal_helper.c: -------------------------------------------------------------------------------- 1 | #ifdef CATS_EFFECT_SIGNAL_HELPER 2 | #include 3 | #include 4 | 5 | typedef void (*Handler)(int); 6 | 7 | int cats_effect_install_handler(int signum, Handler handler) { 8 | int error; 9 | struct sigaction action; 10 | action.sa_handler = handler; 11 | action.sa_flags = 0; 12 | error = sigemptyset(&action.sa_mask); 13 | if (error != 0) { 14 | return error; 15 | } 16 | error = sigaddset(&action.sa_mask, 13); // mask SIGPIPE 17 | if (error != 0) { 18 | return error; 19 | } 20 | return sigaction(signum, &action, NULL); 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /core/native/src/main/scala/cats/effect/IOCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | private[effect] abstract class IOCompanionPlatform extends IOCompanionMultithreadedPlatform { 20 | this: IO.type => 21 | } 22 | -------------------------------------------------------------------------------- /core/native/src/main/scala/cats/effect/InterruptThrowable.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | private[effect] object InterruptThrowable { 20 | def apply(t: Throwable): Boolean = t match { 21 | case _: InterruptedException => true 22 | case _ => false 23 | } 24 | 25 | def ClosedByInterrupt(t: Throwable): Boolean = t match { 26 | case _ => false 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/native/src/main/scala/cats/effect/Platform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | private object Platform { 20 | final val isJs = false 21 | final val isJvm = false 22 | final val isNative = true 23 | 24 | class static extends scala.annotation.Annotation 25 | type safePublish = scala.scalanative.annotation.safePublish 26 | type volatileNative = scala.volatile 27 | } 28 | -------------------------------------------------------------------------------- /core/native/src/main/scala/cats/effect/tracing/TracingConstants.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package tracing 19 | 20 | private[effect] object TracingConstants { 21 | 22 | private[this] final val stackTracingMode: String = 23 | Option(System.getenv("CATS_EFFECT_TRACING_MODE")).filterNot(_.isEmpty).getOrElse("cached") 24 | 25 | final val isCachedStackTracing: Boolean = stackTracingMode.equalsIgnoreCase("cached") 26 | 27 | final val isFullStackTracing: Boolean = stackTracingMode.equalsIgnoreCase("full") 28 | 29 | final val isStackTracing = isFullStackTracing || isCachedStackTracing 30 | } 31 | -------------------------------------------------------------------------------- /core/native/src/main/scala/cats/effect/unsafe/WorkStealingThreadPoolPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package unsafe 19 | 20 | import scala.scalanative.libc.errno._ 21 | import scala.scalanative.libc.string._ 22 | import scala.scalanative.meta.LinktimeInfo 23 | import scala.scalanative.posix.time._ 24 | import scala.scalanative.posix.timeOps._ 25 | import scala.scalanative.unsafe._ 26 | 27 | trait WorkStealingThreadPoolPlatform[P <: AnyRef] extends Scheduler { 28 | this: WorkStealingThreadPool[P] => 29 | 30 | // TODO cargo culted from EventLoopExecutorScheduler.scala 31 | override def nowMicros(): Long = 32 | if (LinktimeInfo.isFreeBSD || LinktimeInfo.isLinux || LinktimeInfo.isMac) { 33 | val ts = stackalloc[timespec]() 34 | if (clock_gettime(CLOCK_REALTIME, ts) != 0) 35 | throw new RuntimeException(fromCString(strerror(errno))) 36 | ts.tv_sec.toLong * 1000000 + ts.tv_nsec.toLong / 1000 37 | } else { 38 | super.nowMicros() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/ExitCode.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | /** 20 | * Represents the exit code of an application. 21 | * 22 | * `code` is constrained to a range from 0 to 255, inclusive. 23 | */ 24 | sealed abstract case class ExitCode private (code: Int) 25 | 26 | object ExitCode { 27 | 28 | /** 29 | * Creates an `ExitCode`. 30 | * 31 | * @param i 32 | * the value whose 8 least significant bits are used to construct an exit code within the 33 | * valid range. 34 | */ 35 | def apply(i: Int): ExitCode = new ExitCode(i & 0xff) {} 36 | 37 | val Success: ExitCode = ExitCode(0) 38 | val Error: ExitCode = ExitCode(1) 39 | } 40 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/implicits.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | object implicits extends syntax.AllSyntax with instances.AllInstances 20 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/instances/AllInstances.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package instances 19 | 20 | trait AllInstances extends kernel.instances.GenSpawnInstances 21 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/instances/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | package object instances { 20 | 21 | object all extends AllInstances 22 | 23 | object spawn extends kernel.instances.GenSpawnInstances 24 | } 25 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/metrics/CpuStarvationWarningMetrics.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.metrics 18 | 19 | import scala.concurrent.duration.FiniteDuration 20 | 21 | final case class CpuStarvationWarningMetrics( 22 | occurrenceTime: FiniteDuration, 23 | clockDrift: FiniteDuration, 24 | starvationThreshold: Double, 25 | starvationInterval: FiniteDuration) 26 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/syntax/AllSyntax.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package syntax 19 | 20 | trait AllSyntax extends kernel.syntax.AllSyntax with std.syntax.AllSyntax with DispatcherSyntax 21 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/syntax/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | package object syntax { 20 | 21 | object all extends AllSyntax 22 | 23 | object monadCancel extends kernel.syntax.MonadCancelSyntax 24 | object spawn extends kernel.syntax.GenSpawnSyntax 25 | object concurrent extends kernel.syntax.GenConcurrentSyntax 26 | object temporal extends kernel.syntax.GenTemporalSyntax 27 | object async extends kernel.syntax.AsyncSyntax 28 | object resource extends kernel.syntax.ResourceSyntax 29 | object clock extends kernel.syntax.ClockSyntax 30 | 31 | object supervisor extends std.syntax.SupervisorSyntax 32 | object dispatcher extends DispatcherSyntax 33 | } 34 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/tracing/TracingEvent.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.tracing 18 | 19 | private[effect] sealed trait TracingEvent extends Serializable 20 | 21 | private[effect] object TracingEvent { 22 | final class StackTrace extends Throwable with TracingEvent 23 | } 24 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/unsafe/FiberMonitorShared.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe 18 | 19 | import cats.effect.{IOFiber, Trace} 20 | import cats.effect.tracing.Tracing 21 | 22 | private[unsafe] abstract class FiberMonitorShared { 23 | 24 | protected val newline = System.lineSeparator() 25 | protected val doubleNewline = s"$newline $newline" 26 | 27 | protected def fiberString(fiber: IOFiber[?], trace: Trace, status: String): String = { 28 | val id = System.identityHashCode(fiber).toHexString 29 | val prefixedTrace = if (trace.toList.isEmpty) "" else newline + Tracing.prettyPrint(trace) 30 | s"cats.effect.IOFiber@$id $status$prefixedTrace" 31 | } 32 | 33 | protected def printFibers(fibers: Map[IOFiber[?], Trace], status: String)( 34 | print: String => Unit): Unit = 35 | fibers foreach { 36 | case (fiber, trace) => 37 | print(doubleNewline) 38 | print(fiberString(fiber, trace, status)) 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/unsafe/Scheduler.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe 18 | 19 | import scala.concurrent.duration.FiniteDuration 20 | 21 | trait Scheduler { 22 | 23 | /** 24 | * Schedules a side-effect to run after the delay interval. Produces another side-effect which 25 | * cancels the scheduling. 26 | */ 27 | def sleep(delay: FiniteDuration, task: Runnable): Runnable 28 | 29 | def nowMillis(): Long 30 | 31 | def nowMicros(): Long = 32 | nowMillis() * 1000 33 | 34 | def monotonicNanos(): Long 35 | } 36 | 37 | object Scheduler extends SchedulerCompanionPlatform 38 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/unsafe/implicits.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe 18 | 19 | object implicits { 20 | implicit def global: IORuntime = IORuntime.global 21 | } 22 | -------------------------------------------------------------------------------- /core/shared/src/main/scala/cats/effect/unsafe/metrics/IORuntimeMetrics.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe.metrics 18 | 19 | /** 20 | * The runtime-specific metrics. 21 | */ 22 | trait IORuntimeMetrics extends IORuntimeMetricsPlatform { 23 | 24 | /** 25 | * Returns starvation-specific metrics. 26 | * 27 | * @example 28 | * {{{ 29 | * val runtime: IORuntime = ??? 30 | * val maxDrift = runtime.metrics.cpuStarvation.clockDriftMax() 31 | * }}} 32 | */ 33 | def cpuStarvation: CpuStarvationMetrics 34 | 35 | private[effect] def cpuStarvationSampler: CpuStarvationSampler 36 | } 37 | 38 | object IORuntimeMetrics extends IORuntimeMetricsCompanionPlatform 39 | -------------------------------------------------------------------------------- /docs/assets/dispatcher.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typelevel/cats-effect/768668a57fe8f8cef2bd6ec61d311da9a7a2629b/docs/assets/dispatcher.jpeg -------------------------------------------------------------------------------- /docs/assets/hierarchy-impure.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typelevel/cats-effect/768668a57fe8f8cef2bd6ec61d311da9a7a2629b/docs/assets/hierarchy-impure.jpeg -------------------------------------------------------------------------------- /docs/assets/semaphore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typelevel/cats-effect/768668a57fe8f8cef2bd6ec61d311da9a7a2629b/docs/assets/semaphore.png -------------------------------------------------------------------------------- /docs/core/jlink.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: jlink 3 | title: Jlink image 4 | --- 5 | 6 | While Scala does not officially offer support for the 7 | [Java Platform Module System](https://openjdk.java.net/projects/jigsaw/spec/), 8 | and Cats Effect is itself built using JDK 8, Cats Effect applications can be 9 | run on JDKs derived using `jlink` (bundling only the classes required for 10 | the application to run). 11 | 12 | Cats Effect applications only depend on JDK classes defined in the `java.base` 13 | module. Building a JDK derived using `jlink` always contains these classes, so 14 | projects that depend on `cats-effect` jars can be run out-of-the-box without 15 | additional configuration. 16 | 17 | There is one exception to this. The `java.base` module does not bundle support 18 | for POSIX signals, which means that the 19 | [a fiber dump](./fiber-dumps.md) functionality cannot be 20 | triggered by sending POSIX signals to the Cats Effect application process. 21 | 22 | The POSIX signal functionality can be restored by adding a dependency on the 23 | `jdk.unsupported` module, which unlocks access to the `sun.misc.Signal` API. 24 | 25 | ## sbt-native-packager 26 | This sbt plugin can build `jlink` derived JDKs and can be configured to include 27 | the `jdk.unsupported` module as follows: 28 | 29 | ```scala 30 | .settings( 31 | jlinkModules += "jdk.unsupported" 32 | ) 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/std/atomic-cell.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: atomic-cell 3 | title: Atomic Cell 4 | --- 5 | 6 | A synchronized, concurrent, mutable reference. 7 | 8 | Provides safe concurrent access and modification of its contents, by ensuring only one fiber 9 | can operate on them at the time. Thus, all operations except `get` may semantically block the 10 | calling fiber. 11 | 12 | ```scala mdoc:silent 13 | abstract class AtomicCell[F[_], A] { 14 | def get: F[A] 15 | def set(a: A): F[Unit] 16 | def modify[B](f: A => (A, B)): F[B] 17 | def evalModify[B](f: A => F[(A, B)]): F[B] 18 | def evalUpdate(f: A => F[A]): F[Unit] 19 | // ... and more 20 | } 21 | ``` 22 | 23 | ## Using `AtomicCell` 24 | 25 | The `AtomicCell` can be treated as a combination of `Mutex` and `Ref`: 26 | ```scala mdoc:reset:silent 27 | import cats.effect.{IO, Ref} 28 | import cats.effect.std.Mutex 29 | 30 | trait State 31 | class Service(mtx: Mutex[IO], ref: Ref[IO, State]) { 32 | def modify(f: State => IO[State]): IO[Unit] = 33 | mtx.lock.surround { 34 | for { 35 | current <- ref.get 36 | next <- f(current) 37 | _ <- ref.set(next) 38 | } yield () 39 | } 40 | } 41 | ``` 42 | 43 | The following is the equivalent of the example above: 44 | ```scala mdoc:reset:silent 45 | import cats.effect.IO 46 | import cats.effect.std.AtomicCell 47 | 48 | trait State 49 | class Service(cell: AtomicCell[IO, State]) { 50 | def modify(f: State => IO[State]): IO[Unit] = 51 | cell.evalUpdate(current => f(current)) 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /docs/std/backpressure.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: backpressure 3 | title: Backpressure 4 | --- 5 | 6 | `Backpressure` allows running effects through the rate-limiting strategy. 7 | `Backpressure` can be utilized in a scenario where a large number of tasks need to be processed, but only a certain number of resources are available. 8 | In other words, backpressure is needed when there is not enough time or resources available for processing all the requests on your system. 9 | 10 | `Backpressure` has two strategies that work as follows: 11 | - `Lossy` - an effect **will not be** run in the presence of backpressure. 12 | - `Lossless` - an effect **will run** in the presence of backpressure. However, the effect will semantically block until backpressure is alleviated. 13 | 14 | ```scala 15 | trait Backpressure[F[_]] { 16 | def metered[A](f: F[A]): F[Option[A]] 17 | } 18 | ``` 19 | 20 | ## Using `Backpressure` 21 | 22 | ```scala mdoc:silent 23 | import cats.effect.IO 24 | import cats.effect.std.Backpressure 25 | import scala.concurrent.duration._ 26 | 27 | val program = 28 | for { 29 | backpressure <- Backpressure[IO](Backpressure.Strategy.Lossless, 1) 30 | f1 <- backpressure.metered(IO.sleep(1.second) *> IO.pure(1)).start 31 | f2 <- backpressure.metered(IO.sleep(1.second) *> IO.pure(1)).start 32 | res1 <- f1.joinWithNever 33 | res2 <- f2.joinWithNever 34 | } yield (res1, res2) 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/std/countdown-latch.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: countdown-latch 3 | title: Count Down Latch 4 | --- 5 | 6 | A one-shot concurrency primitive that blocks any fibers that wait on 7 | it. It is initialized with a positive integer `n` latches and waiting 8 | fibers are semantically blocked until all `n` latches are released. 9 | After this, further `await`s are no-ops (equivalent to `IO.unit`). 10 | 11 | ```scala 12 | trait CountDownLatch[F[_]] { 13 | 14 | def release: F[Unit] 15 | 16 | def await: F[Unit] 17 | 18 | } 19 | ``` 20 | 21 | Cancelation of `await` is supported. 22 | 23 | ```scala mdoc 24 | import cats.implicits._ 25 | import cats.effect._ 26 | import cats.effect.std.CountDownLatch 27 | import cats.effect.unsafe.implicits.global 28 | 29 | val run = ( 30 | for { 31 | c <- CountDownLatch[IO](2) 32 | f <- (c.await >> IO.println("Countdown latch unblocked")).start 33 | _ <- c.release 34 | _ <- IO.println("Before latch is unblocked") 35 | _ <- c.release 36 | _ <- f.join 37 | } yield () 38 | ) 39 | 40 | run.unsafeRunSync() 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/std/cyclic-barrier.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: cyclic-barrier 3 | title: Cyclic Barrier 4 | --- 5 | 6 | A re-usable synchronization primitive that allows a set of 7 | fibers to wait until they've all reached the same point. 8 | 9 | ```scala 10 | 11 | trait CyclicBarrier[F[_]] { 12 | 13 | def await: F[Unit] 14 | 15 | } 16 | ``` 17 | 18 | A cyclic barrier is initialized with a positive integer `n` and 19 | fibers which call `await` are semantically blocked until `n` of 20 | them have invoked `await`, at which point all of them are unblocked 21 | and the cyclic barrier is reset. 22 | 23 | `await` cancelation is supported, in which case the number of 24 | fibers required to unblock the cyclic barrier is incremented again. 25 | 26 | ```scala mdoc 27 | import cats.implicits._ 28 | import cats.effect._ 29 | import cats.effect.std.CyclicBarrier 30 | import cats.effect.unsafe.implicits.global 31 | import scala.concurrent.duration._ 32 | 33 | val run = (for { 34 | b <- CyclicBarrier[IO](2) 35 | f1 <- (IO.println("fast fiber before barrier") >> 36 | b.await >> 37 | IO.println("fast fiber after barrier") 38 | ) .start 39 | f2 <- (IO.sleep(1.second) >> 40 | IO.println("slow fiber before barrier") >> 41 | IO.sleep(1.second) >> 42 | b.await >> 43 | IO.println("slow fiber after barrier") 44 | ).start 45 | _ <- (f1.join, f2.join).tupled 46 | } yield ()) 47 | 48 | run.unsafeRunSync() 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/std/env.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: env 3 | title: Env 4 | --- 5 | 6 | `Env` provides a handy way of reading the process's environment variables. 7 | 8 | ```scala 9 | trait Env[F[_]] { 10 | def get(name: String): F[Option[String]] 11 | def entries: F[Iterable[(String, String)]] 12 | } 13 | ``` 14 | 15 | ```scala mdoc:silent 16 | import cats.effect.IO 17 | import cats.effect.std.Env 18 | 19 | val program: IO[Unit] = 20 | for { 21 | variable <- Env[IO].get("MY_VARIABLE") 22 | _ <- IO.println(s"The variable is [${variable}]") 23 | } yield () 24 | ``` 25 | 26 | ### Why `def get(name): F[Option[String]]` rather than `def get(name): Option[String]`? 27 | 28 | Technically, environment variables can be set within the **current** process on a POSIX system. 29 | Java doesn't provide that functionality in a public API, but it's possible via JNA API or in Scala Native world. 30 | 31 | Besides the modification, retrieving an environment variable may fail under some circumstances. 32 | For example, the process may throw a `SecurityException` on Windows when the permissions are insufficient. 33 | 34 | Since the library supports multiple platforms (JVM, Scala Native, ScalaJS), the implementation should take 35 | platform-specific peculiarities into the account. 36 | -------------------------------------------------------------------------------- /docs/std/mutex.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: mutex 3 | title: Mutex 4 | --- 5 | 6 | `Mutex` is a concurrency primitive that can be used to give access to a resource to only **one** 7 | fiber at a time. Basically, it's a [`Semaphore`](./semaphore.md) with a single available permit. 8 | 9 | ```scala 10 | trait Mutex[F[_]] { 11 | def lock: Resource[F, Unit] 12 | } 13 | ``` 14 | 15 | **Caution**: This lock is not reentrant, thus this `mutex.lock.surround(mutex.lock.use_)` will 16 | deadlock. 17 | 18 | ## Using `Mutex` 19 | 20 | ```scala mdoc:silent 21 | import cats.effect.{IO, Ref} 22 | import cats.effect.std.Mutex 23 | 24 | trait State 25 | class Service(mutex: Mutex[IO], ref: Ref[IO, State]) { 26 | def withState(f: State => IO[Unit]): IO[Unit] = 27 | mutex.lock.surround { 28 | for { 29 | current <- ref.get 30 | _ <- f(current) 31 | } yield () 32 | } 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/typeclasses/clock.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: clock 3 | title: Clock 4 | --- 5 | 6 | A typeclass that provides effectful monotonic and system time analogous to 7 | `System.nanoTime()` and `System.currentTimeMillis()` 8 | 9 | ```scala 10 | trait Clock[F[_]] { 11 | 12 | def monotonic: F[FiniteDuration] 13 | 14 | def realTime: F[FiniteDuration] 15 | 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /docs/typeclasses/temporal.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: temporal 3 | title: Temporal 4 | --- 5 | 6 | `Temporal` extends `Concurrent` with the ability to suspend a fiber by sleeping for 7 | a specified duration. 8 | 9 | ```scala 10 | firstThing >> Temporal[F].sleep(5.seconds) >> secondThing 11 | ``` 12 | 13 | Of course this could be achieved by `Sync[F].delay(Thread.sleep(duration))` but 14 | this is a _very bad_ idea as it will block a thread from the compute pool (see 15 | the [thread model docs](../thread-model.md) for more details on why this is 16 | bad). Instead, `Temporal[F]#sleep` is assigned its own typeclass and is a 17 | primitive of the implementation that semantically blocks the execution of the 18 | calling fiber by de-scheduling it. Internally a scheduler is used to wait for 19 | the specified duration before rescheduling the fiber. 20 | 21 | The ability to sleep for a specified duration enables us to define powerful 22 | time-dependent derived combinators like `timeoutTo`: 23 | 24 | ```scala 25 | val data = fetchFromRemoteService.timeoutTo(2.seconds, cachedValue) 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/typeclasses/unique.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: unique 3 | title: Unique 4 | --- 5 | 6 | A typeclass which is a source of unique tokens via `unique`. This is a fairly 7 | low-level programming primitive, and is not usually suitable for identifying 8 | business entities at the level of application logic. 9 | 10 | ```scala 11 | trait Unique[F[_]] { 12 | def unique: F[Unique.Token] 13 | } 14 | ``` 15 | 16 | Each evaluation of `unique` is guaranteed to produce a value that is distinct 17 | from any other currently allocated tokens. 18 | 19 | ```scala 20 | val token: F[Unique.Token] = Unique[F].unique 21 | (token, token).mapN { (x, y) => x === y } <-> Monad[F].pure(false) 22 | ``` 23 | 24 | This uniqueness guarantee applies only in respect of equality comparison between 25 | `Unique.Token` instances; it is not possible to serialize these instances or 26 | convert them to another form. (The `hashCode` method, for example, is not guaranteed 27 | to return a unique value.) Therefore, these values are meaningful only within a single 28 | application process and cannot (for example) be shared across network boundaries, 29 | persisted to a database, or exposed to end-users. If you need globally unique token 30 | that is suitable for purposes such as these, use a 31 | [UUID](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html) instead. 32 | 33 | Both `Sync[F]` and `Spawn[F]` extend `Unique[F]` as both typeclasses trivially 34 | have the ability to create unique values via `delay(new Unique.Token())` and 35 | `start` respectively (fibers are always unique). 36 | -------------------------------------------------------------------------------- /example/js/src/main/scala/cats/effect/example/Example.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package example 19 | 20 | object Example extends IOApp { 21 | 22 | def run(args: List[String]): IO[ExitCode] = 23 | for { 24 | leftF <- (printFive(args(0)) >> IO.cede >> printFive(args(0))).start 25 | rightF <- (printFive(args(1)) >> IO.cede >> printFive(args(1))).start 26 | _ <- leftF.join 27 | _ <- rightF.join 28 | } yield ExitCode(2) 29 | 30 | def printFive(text: String): IO[Unit] = 31 | IO(println(text)).replicateA(5).void 32 | } 33 | -------------------------------------------------------------------------------- /example/jvm/src/main/scala/cats/effect/example/Example.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package example 19 | 20 | object Example extends IOApp.Simple { 21 | 22 | def run: IO[Unit] = 23 | (IO(println("started")) >> IO.never).onCancel(IO(println("canceled"))) 24 | } 25 | -------------------------------------------------------------------------------- /example/native/src/main/scala/cats/effect/example/Example.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package example 19 | 20 | object Example extends IOApp { 21 | def run(args: List[String]): IO[ExitCode] = 22 | (IO.println(args(0)).replicateA_(5) >> 23 | IO.println(args(1)).replicateA_(5)).replicateA_(2).as(ExitCode(2)) 24 | } 25 | -------------------------------------------------------------------------------- /example/test-js.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script mostly just ensures that we can use node to run an example application. 4 | 5 | set -euo pipefail # STRICT MODE 6 | IFS=$'\n\t' # http://redsymbol.net/articles/unofficial-bash-strict-mode/ 7 | 8 | cd $(dirname $0)/.. 9 | 10 | sbt ++$1 exampleJS/fastOptJS 11 | 12 | output=$(mktemp) 13 | expected=$(mktemp) 14 | 15 | cd example/js/target/scala-$(echo $1 | sed -E 's/^(2\.[0-9]+)\.[0-9]+$/\1/')/ 16 | 17 | set +e 18 | node cats-effect-example-fastopt.js left right > $output 19 | result=$? 20 | set -e 21 | 22 | if [[ $result -ne 2 ]]; then 23 | exit 1 24 | fi 25 | 26 | echo $'left 27 | left 28 | left 29 | left 30 | left 31 | right 32 | right 33 | right 34 | right 35 | right 36 | left 37 | left 38 | left 39 | left 40 | left 41 | right 42 | right 43 | right 44 | right 45 | right' > $expected 46 | 47 | exec diff $output $expected 48 | -------------------------------------------------------------------------------- /example/test-jvm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script tests to ensure that the crazy sbt detection logic in 4 | # IOApp is actually working and correctly forwards cancelation on to 5 | # the unforked subprocess 6 | 7 | set -euo pipefail # STRICT MODE 8 | IFS=$'\n\t' # http://redsymbol.net/articles/unofficial-bash-strict-mode/ 9 | 10 | output=$(mktemp) 11 | 12 | await-output() { 13 | local c=0 14 | until (cat $output | grep "$1" > /dev/null) || [[ $c -gt 30 ]]; do 15 | sleep 1 16 | c=$(($c+1)) 17 | done 18 | 19 | if [[ $c -gt 60 ]]; then 20 | echo -e "\e[31mTimed out waiting for '$1' in output\e[0m" 21 | return -1 22 | else 23 | return 0 24 | fi 25 | } 26 | 27 | cd $(dirname $0)/.. 28 | 29 | echo -e "\e[32mRunning sbt...\e[0m" 30 | sbt ++$1 exampleJVM/run &> >(tee $output) & 31 | 32 | await-output started 33 | echo -e "\e[32mKilling sbt\e[0m" 34 | kill %1 35 | await-output canceled 36 | kill %1 || : 37 | 38 | rm $output 39 | -------------------------------------------------------------------------------- /example/test-native.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script mostly just ensures that we can use native to run an example application. 4 | 5 | set -euo pipefail # STRICT MODE 6 | IFS=$'\n\t' # http://redsymbol.net/articles/unofficial-bash-strict-mode/ 7 | 8 | cd $(dirname $0)/.. 9 | 10 | sbt ++$1 exampleNative/nativeLink 11 | 12 | output=$(mktemp) 13 | expected=$(mktemp) 14 | 15 | cd example/native/target/scala-$(echo $1 | sed -E 's/^(2\.[0-9]+)\.[0-9]+$/\1/')/ 16 | 17 | set +e 18 | ./cats-effect-example left right > $output 19 | result=$? 20 | set -e 21 | 22 | if [[ $result -ne 2 ]]; then 23 | exit 1 24 | fi 25 | 26 | echo $'left 27 | left 28 | left 29 | left 30 | left 31 | right 32 | right 33 | right 34 | right 35 | right 36 | left 37 | left 38 | left 39 | left 40 | left 41 | right 42 | right 43 | right 44 | right 45 | right' > $expected 46 | 47 | exec diff $output $expected 48 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Provision a dev environment"; 3 | 4 | inputs = { 5 | typelevel-nix.url = "github:typelevel/typelevel-nix"; 6 | nixpkgs.follows = "typelevel-nix/nixpkgs"; 7 | flake-utils.follows = "typelevel-nix/flake-utils"; 8 | }; 9 | 10 | outputs = { self, nixpkgs, flake-utils, typelevel-nix }: 11 | flake-utils.lib.eachDefaultSystem (system: 12 | let 13 | pkgs = import nixpkgs { 14 | inherit system; 15 | overlays = [ typelevel-nix.overlays.default ]; 16 | }; 17 | 18 | mkShell = jdk: pkgs.devshell.mkShell { 19 | imports = [ typelevel-nix.typelevelShell ]; 20 | name = "cats-effect"; 21 | typelevelShell = { 22 | jdk.package = jdk; 23 | nodejs.enable = true; 24 | native.enable = true; 25 | nodejs.package = pkgs.nodejs-18_x; 26 | }; 27 | }; 28 | in 29 | rec { 30 | devShell = mkShell pkgs.jdk8; 31 | 32 | devShells = { 33 | "temurin@8" = mkShell pkgs.temurin-bin-8; 34 | "temurin@11" = mkShell pkgs.temurin-bin-11; 35 | "temurin@17" = mkShell pkgs.temurin-bin-17; 36 | }; 37 | } 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /graalvm-example/src/main/scala/cats/effect/example/Example.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package example 19 | 20 | import cats._ 21 | import cats.effect._ 22 | import cats.syntax.all._ 23 | 24 | object GraalVMExample extends IOApp.Simple { 25 | 26 | def run = foo[IO] *> IO.println("grrrraal") 27 | 28 | def foo[F[_]: Async: Parallel] = Async[F].unit &> Async[F].unit 29 | 30 | } 31 | -------------------------------------------------------------------------------- /images/cats-effect-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typelevel/cats-effect/768668a57fe8f8cef2bd6ec61d311da9a7a2629b/images/cats-effect-logo.png -------------------------------------------------------------------------------- /images/contention.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typelevel/cats-effect/768668a57fe8f8cef2bd6ec61d311da9a7a2629b/images/contention.png -------------------------------------------------------------------------------- /kernel-testkit/shared/src/main/scala/cats/effect/kernel/testkit/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | import cats.data.Kleisli 20 | 21 | package object testkit { 22 | private[effect] type TimeT[F[_], A] = Kleisli[F, Time, A] 23 | } 24 | -------------------------------------------------------------------------------- /kernel/js/src/main/scala/cats/effect/kernel/ClockPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | import scala.scalajs.js 20 | 21 | private[effect] trait ClockPlatform[F[_]] { self: Clock[F] => 22 | 23 | def realTimeDate: F[js.Date] = 24 | self.applicative.map(self.realTime)(d => new js.Date(d.toMillis.toDouble)) 25 | } 26 | -------------------------------------------------------------------------------- /kernel/js/src/main/scala/cats/effect/kernel/ResourcePlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | /** 20 | * JS-specific Resource methods 21 | */ 22 | private[effect] trait ResourcePlatform 23 | -------------------------------------------------------------------------------- /kernel/jvm-native/src/main/scala/cats/effect/kernel/ClockPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | import java.time.{Instant, ZoneOffset, ZonedDateTime} 20 | 21 | private[effect] trait ClockPlatform[F[_]] extends Serializable { self: Clock[F] => 22 | def realTimeInstant: F[Instant] = { 23 | self.applicative.map(self.realTime)(d => Instant.EPOCH.plusNanos(d.toNanos)) 24 | } 25 | 26 | def realTimeZonedDateTime: F[ZonedDateTime] = 27 | self.applicative.map(realTimeInstant)(d => ZonedDateTime.ofInstant(d, ZoneOffset.UTC)) 28 | } 29 | -------------------------------------------------------------------------------- /kernel/native/src/main/scala/cats/effect/kernel/AsyncPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | private[kernel] trait AsyncPlatform[F[_]] 20 | -------------------------------------------------------------------------------- /kernel/native/src/main/scala/cats/effect/kernel/ResourcePlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | private[effect] trait ResourcePlatform extends Serializable 20 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala-2.13/cats/effect/kernel/syntax/GenTemporalSyntaxCompat.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel.syntax 18 | 19 | private[syntax] trait GenTemporalOps_CompanionCompat 20 | 21 | private[syntax] trait GenTemporalOpsCompanionCompat 22 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala-3/cats/effect/kernel/syntax/GenTemporalSyntaxCompat.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel.syntax 18 | 19 | private[syntax] trait GenTemporalOps_CompanionCompat 20 | 21 | private[syntax] trait GenTemporalOpsCompanionCompat 22 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/CancelScope.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | sealed trait CancelScope extends Product with Serializable 20 | 21 | object CancelScope { 22 | case object Cancelable extends CancelScope 23 | case object Uncancelable extends CancelScope 24 | } 25 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/ParallelF.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | //See https://failex.blogspot.com/2017/04/the-high-cost-of-anyval-subclasses.html 20 | object Par { 21 | sealed abstract class ParallelFImpl extends Serializable { 22 | type T[F[_], A] 23 | def apply[F[_], A](fa: F[A]): T[F, A] 24 | def value[F[_], A](t: T[F, A]): F[A] 25 | } 26 | 27 | type ParallelF[F[_], A] = instance.T[F, A] 28 | 29 | object ParallelF { 30 | 31 | def apply[F[_], A](fa: F[A]): ParallelF[F, A] = instance[F, A](fa) 32 | 33 | def value[F[_], A](t: ParallelF[F, A]): F[A] = instance.value(t) 34 | 35 | } 36 | 37 | val instance: ParallelFImpl = new ParallelFImpl { 38 | type T[F[_], A] = F[A] 39 | 40 | override def apply[F[_], A](fa: F[A]): T[F, A] = fa 41 | 42 | override def value[F[_], A](t: T[F, A]): F[A] = t 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/Poll.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | import cats.~> 20 | 21 | /** 22 | * @see 23 | * [[MonadCancel]] 24 | */ 25 | trait Poll[F[_]] extends (F ~> F) 26 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/Unique.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | import cats.{Applicative, Hash} 20 | 21 | trait Unique[F[_]] extends Serializable { 22 | def applicative: Applicative[F] 23 | def unique: F[Unique.Token] 24 | } 25 | 26 | object Unique { 27 | 28 | def apply[F[_]](implicit F: Unique[F]): F.type = F 29 | 30 | final class Token extends Serializable 31 | 32 | object Token { 33 | implicit val tokenHash: Hash[Token] = 34 | Hash.fromUniversalHashCode[Token] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/implicits.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | object implicits extends syntax.AllSyntax with instances.AllInstances 20 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/instances/AllInstances.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel.instances 18 | 19 | trait AllInstances extends GenSpawnInstances 20 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/instances/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | package object instances { 20 | 21 | object all extends AllInstances 22 | 23 | object spawn extends GenSpawnInstances 24 | } 25 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | package object kernel { 20 | 21 | type MonadCancelThrow[F[_]] = MonadCancel[F, Throwable] 22 | val MonadCancelThrow = MonadCancel 23 | 24 | type Spawn[F[_]] = GenSpawn[F, Throwable] 25 | val Spawn = GenSpawn 26 | 27 | type Temporal[F[_]] = GenTemporal[F, Throwable] 28 | val Temporal = GenTemporal 29 | 30 | type Concurrent[F[_]] = GenConcurrent[F, Throwable] 31 | val Concurrent = GenConcurrent 32 | 33 | type ParallelF[F[_], A] = Par.ParallelF[F, A] 34 | val ParallelF = Par.ParallelF 35 | } 36 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/syntax/AllSyntax.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel.syntax 18 | 19 | trait AllSyntax 20 | extends MonadCancelSyntax 21 | with GenSpawnSyntax 22 | with GenTemporalSyntax 23 | with GenConcurrentSyntax 24 | with AsyncSyntax 25 | with ResourceSyntax 26 | with ClockSyntax 27 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/syntax/ClockSyntax.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel.syntax 18 | 19 | import cats.effect.kernel.Clock 20 | 21 | import scala.concurrent.duration.FiniteDuration 22 | 23 | trait ClockSyntax { 24 | implicit def clockOps[F[_], A](wrapped: F[A]): ClockOps[F, A] = 25 | new ClockOps(wrapped) 26 | } 27 | 28 | final class ClockOps[F[_], A] private[syntax] (private val wrapped: F[A]) extends AnyVal { 29 | 30 | def timed(implicit F: Clock[F]): F[(FiniteDuration, A)] = 31 | F.timed(wrapped) 32 | } 33 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/syntax/ResourceSyntax.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel.syntax 18 | 19 | import cats.effect.kernel.Resource 20 | 21 | trait ResourceSyntax { 22 | implicit def effectResourceOps[F[_], A](wrapped: F[A]): EffectResourceOps[F, A] = 23 | new EffectResourceOps(wrapped) 24 | } 25 | 26 | final class EffectResourceOps[F[_], A] private[syntax] (private[syntax] val wrapped: F[A]) 27 | extends AnyVal { 28 | def toResource: Resource[F, A] = Resource.eval(wrapped) 29 | } 30 | -------------------------------------------------------------------------------- /kernel/shared/src/main/scala/cats/effect/kernel/syntax/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.kernel 18 | 19 | package object syntax { 20 | 21 | object all extends AllSyntax 22 | 23 | object monadCancel extends MonadCancelSyntax 24 | object spawn extends GenSpawnSyntax 25 | object concurrent extends GenConcurrentSyntax 26 | object temporal extends GenTemporalSyntax 27 | object async extends AsyncSyntax 28 | object resource extends ResourceSyntax 29 | object clock extends ClockSyntax 30 | } 31 | -------------------------------------------------------------------------------- /laws/shared/src/main/scala/cats/effect/laws/ClockLaws.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.Applicative 21 | import cats.effect.kernel.Clock 22 | import cats.syntax.all._ 23 | 24 | trait ClockLaws[F[_]] { 25 | 26 | implicit val F: Clock[F] 27 | private implicit def app: Applicative[F] = F.applicative 28 | 29 | def monotonicity = (F.monotonic, F.monotonic).mapN(_ <= _) 30 | } 31 | 32 | object ClockLaws { 33 | def apply[F[_]](implicit F0: Clock[F]): ClockLaws[F] = 34 | new ClockLaws[F] { val F = F0 } 35 | } 36 | -------------------------------------------------------------------------------- /laws/shared/src/main/scala/cats/effect/laws/ClockTests.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.effect.kernel.Clock 21 | 22 | import org.scalacheck._ 23 | import org.typelevel.discipline.Laws 24 | 25 | trait ClockTests[F[_]] extends Laws { 26 | 27 | val laws: ClockLaws[F] 28 | 29 | def clock(implicit exec: F[Boolean] => Prop): RuleSet = { 30 | new RuleSet { 31 | val name = "clock" 32 | val bases: Seq[(String, Laws#RuleSet)] = Nil 33 | val parents: Seq[RuleSet] = Seq() 34 | 35 | val props = Seq("monotonicity" -> exec(laws.monotonicity)) 36 | } 37 | } 38 | } 39 | 40 | object ClockTests { 41 | def apply[F[_]](implicit F0: Clock[F]): ClockTests[F] = 42 | new ClockTests[F] { 43 | val laws = ClockLaws[F] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /laws/shared/src/main/scala/cats/effect/laws/Tolerance.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.laws 18 | 19 | import cats.Applicative 20 | import cats.syntax.all._ 21 | 22 | final case class Tolerance[+A](value: A) 23 | 24 | object Tolerance { 25 | 26 | def apply[A](implicit A: Tolerance[A]): Tolerance[A] = A 27 | 28 | implicit def lift[F[_]: Applicative, A: Tolerance]: Tolerance[F[A]] = 29 | Tolerance(Tolerance[A].value.pure[F]) 30 | } 31 | -------------------------------------------------------------------------------- /laws/shared/src/main/scala/cats/effect/laws/UniqueLaws.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.Applicative 21 | import cats.effect.kernel.Unique 22 | import cats.syntax.all._ 23 | 24 | trait UniqueLaws[F[_]] { 25 | 26 | implicit val F: Unique[F] 27 | private implicit def app: Applicative[F] = F.applicative 28 | 29 | def uniqueness = (F.unique, F.unique).mapN(_ =!= _) 30 | } 31 | 32 | object UniqueLaws { 33 | def apply[F[_]](implicit F0: Unique[F]): UniqueLaws[F] = 34 | new UniqueLaws[F] { val F = F0 } 35 | } 36 | -------------------------------------------------------------------------------- /laws/shared/src/main/scala/cats/effect/laws/UniqueTests.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.effect.kernel.Unique 21 | 22 | import org.scalacheck._ 23 | import org.typelevel.discipline.Laws 24 | 25 | trait UniqueTests[F[_]] extends Laws { 26 | 27 | val laws: UniqueLaws[F] 28 | 29 | def unique(implicit exec: F[Boolean] => Prop): RuleSet = { 30 | new RuleSet { 31 | val name = "unique" 32 | val bases: Seq[(String, Laws#RuleSet)] = Nil 33 | val parents: Seq[RuleSet] = Seq() 34 | 35 | val props = Seq("uniqueness" -> exec(laws.uniqueness)) 36 | } 37 | } 38 | } 39 | 40 | object UniqueTests { 41 | def apply[F[_]](implicit F0: Unique[F]): UniqueTests[F] = 42 | new UniqueTests[F] { 43 | val laws = UniqueLaws[F] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /laws/shared/src/main/scala/cats/effect/laws/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | package object laws { 20 | 21 | // override the one in cats 22 | implicit final class IsEqArrow[A](private val lhs: A) extends AnyVal { 23 | def <->(rhs: A): IsEq[A] = IsEq(lhs, rhs) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /laws/shared/src/test/scala/cats/effect/laws/ClockSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.data.ContT 21 | import cats.effect.kernel.testkit.freeEval._ 22 | 23 | import munit.DisciplineSuite 24 | 25 | class ClockSuite extends DisciplineSuite with BaseSuite { 26 | 27 | // we only need to test the ones that *aren't* also Sync 28 | checkAll("ContT[FreeEitherSync, Int, *]", ClockTests[ContT[FreeEitherSync, Int, *]].clock) 29 | } 30 | -------------------------------------------------------------------------------- /laws/shared/src/test/scala/cats/effect/laws/FreeSyncSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.{Eq, Eval} 21 | import cats.effect.kernel.testkit.{FreeSyncEq, FreeSyncGenerators, SyncTypeGenerators} 22 | import cats.effect.kernel.testkit.freeEval.{syncForFreeT, FreeEitherSync} 23 | import cats.free.FreeT 24 | import cats.laws.discipline.arbitrary._ 25 | 26 | import munit.DisciplineSuite 27 | 28 | class FreeSyncSuite extends DisciplineSuite with BaseSuite with LowPriorityImplicits { 29 | import FreeSyncGenerators._ 30 | import SyncTypeGenerators._ 31 | 32 | implicit val scala_2_12_is_buggy 33 | : Eq[FreeT[Eval, Either[Throwable, *], Either[Int, Either[Throwable, Int]]]] = 34 | eqFreeSync[Either[Throwable, *], Either[Int, Either[Throwable, Int]]] 35 | 36 | checkAll("FreeEitherSync", SyncTests[FreeEitherSync].sync[Int, Int, Int]) 37 | } 38 | 39 | //See the explicitly summoned implicits above - scala 2.12 has weird divergent implicit expansion problems 40 | trait LowPriorityImplicits extends FreeSyncEq {} 41 | -------------------------------------------------------------------------------- /laws/shared/src/test/scala/cats/effect/laws/IorTFreeSyncSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.{Eq, Eval} 21 | import cats.data.IorT 22 | import cats.effect.kernel.testkit.{FreeSyncGenerators, SyncTypeGenerators} 23 | import cats.effect.kernel.testkit.freeEval.{syncForFreeT, FreeEitherSync} 24 | import cats.free.FreeT 25 | import cats.laws.discipline.arbitrary._ 26 | 27 | import munit.DisciplineSuite 28 | 29 | class IorTFreeSyncSuite extends DisciplineSuite with BaseSuite with LowPriorityImplicits { 30 | import FreeSyncGenerators._ 31 | import SyncTypeGenerators._ 32 | 33 | implicit val scala_2_12_is_buggy 34 | : Eq[FreeT[Eval, Either[Throwable, *], Either[Int, Either[Throwable, Int]]]] = 35 | eqFreeSync[Either[Throwable, *], Either[Int, Either[Throwable, Int]]] 36 | 37 | checkAll("IorT[FreeEitherSync]", SyncTests[IorT[FreeEitherSync, Int, *]].sync[Int, Int, Int]) 38 | } 39 | -------------------------------------------------------------------------------- /laws/shared/src/test/scala/cats/effect/laws/KleisliFreeSyncSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.{Eq, Eval} 21 | import cats.data.Kleisli 22 | import cats.effect.kernel.testkit.{FreeSyncGenerators, SyncTypeGenerators} 23 | import cats.effect.kernel.testkit.freeEval.{syncForFreeT, FreeEitherSync} 24 | import cats.free.FreeT 25 | import cats.laws.discipline.MiniInt 26 | import cats.laws.discipline.arbitrary._ 27 | import cats.laws.discipline.eq._ 28 | 29 | import munit.DisciplineSuite 30 | 31 | class KleisliFreeSyncSuite extends DisciplineSuite with BaseSuite with LowPriorityImplicits { 32 | import FreeSyncGenerators._ 33 | import SyncTypeGenerators._ 34 | 35 | implicit val scala_2_12_is_buggy 36 | : Eq[FreeT[Eval, Either[Throwable, *], Either[Int, Either[Throwable, Int]]]] = 37 | eqFreeSync[Either[Throwable, *], Either[Int, Either[Throwable, Int]]] 38 | 39 | checkAll( 40 | "Kleisli[FreeEitherSync]", 41 | SyncTests[Kleisli[FreeEitherSync, MiniInt, *]].sync[Int, Int, Int]) 42 | } 43 | -------------------------------------------------------------------------------- /laws/shared/src/test/scala/cats/effect/laws/OptionTFreeSyncSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.{Eq, Eval} 21 | import cats.data.OptionT 22 | import cats.effect.kernel.testkit.{FreeSyncEq, FreeSyncGenerators, SyncTypeGenerators} 23 | import cats.effect.kernel.testkit.freeEval.{syncForFreeT, FreeEitherSync} 24 | import cats.free.FreeT 25 | import cats.laws.discipline.arbitrary._ 26 | 27 | import munit.DisciplineSuite 28 | 29 | class OptionTFreeSyncSuite extends DisciplineSuite with BaseSuite with FreeSyncEq { 30 | 31 | import FreeSyncGenerators._ 32 | import SyncTypeGenerators._ 33 | 34 | implicit val scala_2_12_is_buggy 35 | : Eq[FreeT[Eval, Either[Throwable, *], Either[Int, Either[Throwable, Int]]]] = 36 | eqFreeSync[Either[Throwable, *], Either[Int, Either[Throwable, Int]]] 37 | 38 | checkAll("OptionT[FreeEitherSync]", SyncTests[OptionT[FreeEitherSync, *]].sync[Int, Int, Int]) 39 | } 40 | -------------------------------------------------------------------------------- /laws/shared/src/test/scala/cats/effect/laws/StateTFreeSyncSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.{Eq, Eval} 21 | import cats.data.StateT 22 | import cats.effect.kernel.testkit.{FreeSyncGenerators, SyncTypeGenerators} 23 | import cats.effect.kernel.testkit.freeEval.{syncForFreeT, FreeEitherSync} 24 | import cats.free.FreeT 25 | import cats.laws.discipline.MiniInt 26 | import cats.laws.discipline.arbitrary._ 27 | 28 | import munit.DisciplineSuite 29 | 30 | class StateTFreeSyncSuite extends DisciplineSuite with BaseSuite with LowPriorityImplicits { 31 | import FreeSyncGenerators._ 32 | import SyncTypeGenerators._ 33 | 34 | implicit val scala_2_12_is_buggy 35 | : Eq[FreeT[Eval, Either[Throwable, *], Either[Int, Either[Throwable, Int]]]] = 36 | eqFreeSync[Either[Throwable, *], Either[Int, Either[Throwable, Int]]] 37 | 38 | checkAll( 39 | "StateT[FreeEitherSync]", 40 | SyncTests[StateT[FreeEitherSync, MiniInt, *]].sync[Int, Int, Int]) 41 | } 42 | -------------------------------------------------------------------------------- /laws/shared/src/test/scala/cats/effect/laws/WriterTFreeSyncSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package laws 19 | 20 | import cats.{Eq, Eval} 21 | import cats.data.WriterT 22 | import cats.effect.kernel.testkit.{FreeSyncGenerators, SyncTypeGenerators} 23 | import cats.effect.kernel.testkit.freeEval.{syncForFreeT, FreeEitherSync} 24 | import cats.free.FreeT 25 | import cats.laws.discipline.arbitrary._ 26 | 27 | import munit.DisciplineSuite 28 | 29 | class WriterTFreeSyncSuite extends DisciplineSuite with BaseSuite with LowPriorityImplicits { 30 | import FreeSyncGenerators._ 31 | import SyncTypeGenerators._ 32 | 33 | implicit val scala_2_12_is_buggy 34 | : Eq[FreeT[Eval, Either[Throwable, *], Either[Int, Either[Throwable, Int]]]] = 35 | eqFreeSync[Either[Throwable, *], Either[Int, Either[Throwable, Int]]] 36 | 37 | checkAll( 38 | "WriterT[FreeEitherSync]", 39 | SyncTests[WriterT[FreeEitherSync, Int, *]].sync[Int, Int, Int]) 40 | } 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "source-map-support": "^0.5.19" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /project/JSEnv.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | sealed abstract class JSEnv 18 | object JSEnv { 19 | case object Firefox extends JSEnv 20 | case object Chrome extends JSEnv 21 | case object NodeJS extends JSEnv 22 | } 23 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.11.1 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | libraryDependencies += "org.scala-js" %% "scalajs-env-selenium" % "1.1.1" 2 | 3 | addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.7.7") 4 | 5 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.18.2") 6 | addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.6") 7 | addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7") 8 | addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.6.5") 9 | addSbtPlugin("com.lightbend.sbt" % "sbt-java-formatter" % "0.8.0") 10 | addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.13.1") 11 | addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.14.3") 12 | addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.3.4") 13 | -------------------------------------------------------------------------------- /scalafix/.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = 3.6.1 2 | maxColumn = 100 3 | spaces.inImportCurlyBraces = true 4 | project.excludeFilters = [ 5 | "v3_0_0/output/*" 6 | ] 7 | -------------------------------------------------------------------------------- /scalafix/README.md: -------------------------------------------------------------------------------- 1 | # Scalafix rules for Cats Effect 2 | 3 | ## How to use 4 | 5 | 1. [Install the Scalafix sbt plugin](https://scalacenter.github.io/scalafix/docs/users/installation) 6 | 1. Run the rules appropriate to your Cats Effect version (see below) 7 | 8 | ## Migration to Cats Effect 3.0.0 9 | 10 | The `v3_0_0` rule migrates Cats Effect 2.x code to Cats Effect 3.0.0. 11 | 12 | First configure the SemanticDB compiler plugin to enable synthetics: 13 | ``` 14 | ThisBuild / scalacOptions += "-P:semanticdb:synthetics:on" 15 | ``` 16 | 17 | Then run Scalafix: 18 | ```sh 19 | sbt ";scalafixEnable ;scalafixAll github:typelevel/cats-effect/v3_0_0?sha=v3.0.0" 20 | ``` 21 | 22 | Finally, bump the Cats Effect version in your build to 3.0.0 and fix any remaining 23 | compile errors. Note that it is important to *not* bump the version before running 24 | Scalafix for the rule to work correctly. 25 | -------------------------------------------------------------------------------- /scalafix/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.11.1 2 | -------------------------------------------------------------------------------- /scalafix/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.14.3") 2 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/input/src/main/scala/fix/BlockerRewrites.scala: -------------------------------------------------------------------------------- 1 | /* 2 | rule = "scala:fix.v3_0_0" 3 | */ 4 | package fix 5 | 6 | import cats.effect.Blocker 7 | import cats.effect.ContextShift 8 | import cats.effect.IO 9 | import cats.effect.Sync 10 | 11 | object BlockerRewrites { 12 | def f1(blocker: Blocker): Int = 0 13 | 14 | def f1_1(blocker: Blocker, i: Int): Int = i 15 | 16 | def f2(blocker: Blocker)(implicit cs: ContextShift[IO]): IO[Unit] = 17 | blocker.delay[IO, Unit](()) 18 | 19 | def f3[F[_]](blocker: Blocker)(implicit cs: ContextShift[F], F: Sync[F]): F[Unit] = 20 | blocker.delay[F, Unit](()) 21 | 22 | def f4[F[_]](blocker: Blocker)(implicit cs: ContextShift[F], F: Sync[F]): F[Unit] = 23 | blocker.delay(()) 24 | 25 | private val b1 = Blocker[IO] 26 | 27 | for { blocker <- Blocker[IO] } yield () 28 | } 29 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/input/src/main/scala/fix/BracketRewrites.scala: -------------------------------------------------------------------------------- 1 | /* 2 | rule = "scala:fix.v3_0_0" 3 | */ 4 | package fix 5 | 6 | import cats.effect.IO 7 | import cats.effect.Sync 8 | import cats.effect.Bracket 9 | import cats.effect.BracketThrow 10 | 11 | object BracketRewrites { 12 | Bracket.apply[IO, Throwable] 13 | 14 | Bracket[IO, Throwable].guarantee(IO.unit)(IO.unit) 15 | 16 | Sync[IO].guarantee(IO.unit)(IO.unit) 17 | 18 | Sync[IO].guarantee( /* comment1 */ IO.unit)(IO.unit) 19 | 20 | Sync[IO].guarantee(IO.unit) /* comment2 */ (IO.unit) 21 | 22 | Sync[IO].guarantee( 23 | IO.unit 24 | )( 25 | IO.unit 26 | ) 27 | 28 | Sync[IO].guarantee(Sync[IO].guarantee(IO.unit)(IO.unit))(IO.unit) 29 | 30 | Sync[IO].guarantee(IO.suspend(Sync[IO].guarantee(IO.unit)(IO.unit)))(IO.unit) 31 | 32 | def f1[F[_], E](implicit F: Bracket[F, E]): Unit = () 33 | 34 | private val x1 = Bracket[IO, Throwable] 35 | x1.guarantee(IO.unit)(IO.unit) 36 | 37 | trait MySync[F[_]] extends Bracket[F, Throwable] 38 | 39 | Bracket[IO, Throwable].uncancelable(IO.unit) 40 | 41 | Bracket[IO, Throwable].uncancelable(Sync[IO].guarantee(IO.unit)(IO.unit)) 42 | 43 | def f2(ev: BracketThrow[IO]): Unit = () 44 | } 45 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/input/src/main/scala/fix/ContextShiftRewrites.scala: -------------------------------------------------------------------------------- 1 | /* 2 | rule = "scala:fix.v3_0_0" 3 | */ 4 | package fix 5 | 6 | import cats.effect.Async 7 | import cats.effect.ContextShift 8 | import cats.effect.{ContextShift => CtxShift} 9 | import cats.effect.Sync 10 | 11 | object ContextShiftRewrites { 12 | def f1[F[_]](implicit cs: ContextShift[F]): Int = 0 13 | 14 | def f2[F[_]](implicit F: Sync[F], cs: CtxShift[F]): Int = 0 15 | 16 | def f3[F[_]](implicit cs: ContextShift[F], F: Sync[F]): Int = 0 17 | 18 | def f4[F[_]](implicit F1: Sync[F], contextShift: ContextShift[F], F2: Sync[F]): Int = 0 19 | 20 | def f5[F[_]](implicit cs: ContextShift[F], F: Async[F]): F[Unit] = cs.shift 21 | } 22 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/input/src/main/scala/fix/IORewrites.scala: -------------------------------------------------------------------------------- 1 | /* 2 | rule = "scala:fix.v3_0_0" 3 | */ 4 | package fix 5 | 6 | import cats.effect.Async 7 | import cats.effect.Concurrent 8 | import cats.effect.IO 9 | import cats.effect.Timer 10 | import scala.concurrent.duration._ 11 | 12 | object IORewrites { 13 | IO.suspend(IO.unit) 14 | 15 | IO.suspend(IO.suspend(IO.pure(0))) 16 | 17 | IO.async((_: Any) => ()) 18 | 19 | IO.suspend(IO.async((_: Any) => ())) 20 | 21 | Async[IO].async((_: Any) => ()) 22 | 23 | Async[IO].suspend(IO.unit) 24 | 25 | def f1(implicit ev: Concurrent[IO]): IO[Unit] = IO.unit 26 | 27 | def f2(implicit timer: Timer[IO]): IO[Unit] = timer.sleep(1.second) 28 | } 29 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/input/src/main/scala/fix/ParallelRewrites.scala: -------------------------------------------------------------------------------- 1 | /* 2 | rule = "scala:fix.v3_0_0" 3 | */ 4 | package fix 5 | 6 | import cats.Parallel 7 | import cats.effect.Concurrent 8 | 9 | object ParallelRewrites { 10 | def f1[F[_]](implicit p: Parallel[F], F: Concurrent[F]): Unit = () 11 | } 12 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/input/src/main/scala/fix/PkgRewrites.scala: -------------------------------------------------------------------------------- 1 | /* 2 | rule = "scala:fix.v3_0_0" 3 | */ 4 | package fix 5 | 6 | import cats.effect.concurrent.{Deferred, Ref, Semaphore} 7 | import cats.effect.{ApplicativeThrow, IO, MonadThrow} 8 | 9 | object PkgRewrites { 10 | locally(Deferred) 11 | locally(cats.effect.concurrent.Deferred) 12 | def f1(d: cats.effect.concurrent.Deferred[IO, Unit]): Deferred[IO, Unit] = d 13 | 14 | locally(Ref) 15 | locally(cats.effect.concurrent.Ref) 16 | def f2(r: cats.effect.concurrent.Ref[IO, Unit]): Ref[IO, Unit] = r 17 | 18 | locally(Semaphore) 19 | locally(cats.effect.concurrent.Semaphore) 20 | def f3(s: cats.effect.concurrent.Semaphore[IO]): Semaphore[IO] = s 21 | 22 | def f4[F[_]](F: ApplicativeThrow[F]): F[Unit] = F.unit 23 | def f5[F[_]](F: MonadThrow[F]): F[Unit] = F.unit 24 | } 25 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/input/src/main/scala/fix/ResourceRewrites.scala: -------------------------------------------------------------------------------- 1 | /* 2 | rule = "scala:fix.v3_0_0" 3 | */ 4 | package fix 5 | 6 | import cats.syntax.all._ 7 | import cats.Parallel 8 | import cats.effect.IO 9 | import cats.effect.Resource 10 | 11 | object ResourceRewrites { 12 | Resource.liftF(IO.unit) 13 | 14 | def f1(implicit p: Parallel[IO]): Resource[IO, Unit] = 15 | Resource.liftF(IO.unit).parZip(Resource.liftF(IO.unit)).void 16 | } 17 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/output/src/main/scala/fix/BlockerRewrites.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import cats.effect.IO 4 | import cats.effect.Sync 5 | import cats.effect.Resource 6 | 7 | object BlockerRewrites { 8 | def f1: Int = 0 9 | 10 | def f1_1(i: Int): Int = i 11 | 12 | def f2: IO[Unit] = 13 | Sync[IO].blocking(()) 14 | 15 | def f3[F[_]](implicit F: Sync[F]): F[Unit] = 16 | Sync[F].blocking(()) 17 | 18 | def f4[F[_]](implicit F: Sync[F]): F[Unit] = 19 | Sync[F].blocking(()) 20 | 21 | private val b1 = Resource.unit[IO] 22 | 23 | for { blocker <- Resource.unit[IO] } yield () 24 | } 25 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/output/src/main/scala/fix/BracketRewrites.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import cats.effect.IO 4 | import cats.effect.Sync 5 | import cats.effect.{ MonadCancel, MonadCancelThrow } 6 | 7 | object BracketRewrites { 8 | MonadCancel.apply[IO, Throwable] 9 | 10 | MonadCancel[IO, Throwable].guarantee(IO.unit, IO.unit) 11 | 12 | Sync[IO].guarantee(IO.unit, IO.unit) 13 | 14 | Sync[IO].guarantee( /* comment1 */ IO.unit, IO.unit) 15 | 16 | Sync[IO].guarantee(IO.unit, /* comment2 */ IO.unit) 17 | 18 | Sync[IO].guarantee( 19 | IO.unit 20 | , 21 | IO.unit 22 | ) 23 | 24 | Sync[IO].guarantee(Sync[IO].guarantee(IO.unit, IO.unit), IO.unit) 25 | 26 | Sync[IO].guarantee(IO.defer(Sync[IO].guarantee(IO.unit, IO.unit)), IO.unit) 27 | 28 | def f1[F[_], E](implicit F: MonadCancel[F, E]): Unit = () 29 | 30 | private val x1 = MonadCancel[IO, Throwable] 31 | x1.guarantee(IO.unit, IO.unit) 32 | 33 | trait MySync[F[_]] extends MonadCancel[F, Throwable] 34 | 35 | MonadCancel[IO, Throwable].uncancelable(_ => IO.unit) 36 | 37 | MonadCancel[IO, Throwable].uncancelable(_ => Sync[IO].guarantee(IO.unit, IO.unit)) 38 | 39 | def f2(ev: MonadCancelThrow[IO]): Unit = () 40 | } 41 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/output/src/main/scala/fix/ContextShiftRewrites.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import cats.effect.Async 4 | import cats.effect.Sync 5 | import cats.effect.Spawn 6 | 7 | object ContextShiftRewrites { 8 | def f1[F[_]]: Int = 0 9 | 10 | def f2[F[_]](implicit F: Sync[F]): Int = 0 11 | 12 | def f3[F[_]](implicit F: Sync[F]): Int = 0 13 | 14 | def f4[F[_]](implicit F1: Sync[F], F2: Sync[F]): Int = 0 15 | 16 | def f5[F[_]](implicit F: Async[F]): F[Unit] = Spawn[F].cede 17 | } 18 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/output/src/main/scala/fix/IORewrites.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import cats.effect.Async 4 | import cats.effect.Concurrent 5 | import cats.effect.IO 6 | import scala.concurrent.duration._ 7 | import cats.effect.Temporal 8 | 9 | object IORewrites { 10 | IO.defer(IO.unit) 11 | 12 | IO.defer(IO.defer(IO.pure(0))) 13 | 14 | IO.async_((_: Any) => ()) 15 | 16 | IO.defer(IO.async_((_: Any) => ())) 17 | 18 | Async[IO].async_((_: Any) => ()) 19 | 20 | Async[IO].defer(IO.unit) 21 | 22 | def f1: IO[Unit] = IO.unit 23 | 24 | def f2(implicit timer: Temporal[IO]): IO[Unit] = timer.sleep(1.second) 25 | } 26 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/output/src/main/scala/fix/ParallelRewrites.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import cats.Parallel 4 | import cats.effect.Concurrent 5 | import cats.effect.implicits._ 6 | 7 | object ParallelRewrites { 8 | def f1[F[_]](implicit F: Concurrent[F]): Unit = () 9 | } 10 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/output/src/main/scala/fix/PkgRewrites.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import cats.effect.IO 4 | import cats.{ ApplicativeThrow, MonadThrow } 5 | import cats.effect.{ Deferred, Ref } 6 | import cats.effect.std.Semaphore 7 | 8 | object PkgRewrites { 9 | locally(Deferred) 10 | locally(_root_.cats.effect.Deferred) 11 | def f1(d: _root_.cats.effect.Deferred[IO, Unit]): Deferred[IO, Unit] = d 12 | 13 | locally(Ref) 14 | locally(_root_.cats.effect.Ref) 15 | def f2(r: _root_.cats.effect.Ref[IO, Unit]): Ref[IO, Unit] = r 16 | 17 | locally(Semaphore) 18 | locally(cats.effect.std.Semaphore) 19 | def f3(s: cats.effect.std.Semaphore[IO]): Semaphore[IO] = s 20 | 21 | def f4[F[_]](F: ApplicativeThrow[F]): F[Unit] = F.unit 22 | def f5[F[_]](F: MonadThrow[F]): F[Unit] = F.unit 23 | } 24 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/output/src/main/scala/fix/ResourceRewrites.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import cats.syntax.all._ 4 | import cats.Parallel 5 | import cats.effect.IO 6 | import cats.effect.Resource 7 | 8 | object ResourceRewrites { 9 | Resource.eval(IO.unit) 10 | 11 | def f1(implicit p: Parallel[IO]): Resource[IO, Unit] = 12 | Resource.eval(IO.unit).both(Resource.eval(IO.unit)).void 13 | } 14 | -------------------------------------------------------------------------------- /scalafix/v3_0_0/tests/src/test/scala/fix/CatsEffectTests.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import org.scalatest.funsuite.AnyFunSuiteLike 4 | import scalafix.testkit.AbstractSemanticRuleSuite 5 | 6 | class CatsEffectTests extends AbstractSemanticRuleSuite with AnyFunSuiteLike { 7 | runAllTests() 8 | } 9 | -------------------------------------------------------------------------------- /scalafix/v3_3_0/input/src/main/scala/fix/InterruptibleRewrites.scala: -------------------------------------------------------------------------------- 1 | /* 2 | rule = "scala:fix.v3_3_0" 3 | */ 4 | package fix 5 | 6 | import cats.effect.{IO, Sync} 7 | 8 | object InterruptibleRewrites { 9 | IO.interruptible(true)(IO.unit) 10 | 11 | IO.interruptible(false)(IO.unit) 12 | 13 | Sync[IO].interruptible(true)(IO.unit) 14 | 15 | Sync[IO].interruptible(false)(IO.unit) 16 | 17 | def f[F[_]](implicit F: Sync[F]): F[Unit] = F.interruptible(true)(IO.unit) 18 | } 19 | -------------------------------------------------------------------------------- /scalafix/v3_3_0/output/src/main/scala/fix/InterruptibleRewrites.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import cats.effect.{IO, Sync} 4 | 5 | object InterruptibleRewrites { 6 | IO.interruptibleMany(IO.unit) 7 | 8 | IO.interruptible(IO.unit) 9 | 10 | Sync[IO].interruptibleMany(IO.unit) 11 | 12 | Sync[IO].interruptible(IO.unit) 13 | 14 | def f[F[_]](implicit F: Sync[F]): F[Unit] = Sync[F].interruptibleMany(IO.unit) 15 | } 16 | -------------------------------------------------------------------------------- /scalafix/v3_3_0/tests/src/test/scala/fix/CatsEffectTests.scala: -------------------------------------------------------------------------------- 1 | package fix 2 | 3 | import org.scalatest.funsuite.AnyFunSuiteLike 4 | import scalafix.testkit.AbstractSemanticRuleSuite 5 | 6 | class CatsEffectTests extends AbstractSemanticRuleSuite with AnyFunSuiteLike { 7 | runAllTests() 8 | } 9 | -------------------------------------------------------------------------------- /scripts/data/scastie.sbt: -------------------------------------------------------------------------------- 1 | scalacOptions ++= Seq( 2 | "-deprecation", 3 | "-encoding", 4 | "UTF-8", 5 | "-feature", 6 | "-unchecked" 7 | ) 8 | -------------------------------------------------------------------------------- /scripts/data/scastie.scala: -------------------------------------------------------------------------------- 1 | import cats.effect.{IO, IOApp} 2 | import cats.effect.std.Random 3 | 4 | import scala.concurrent.duration._ 5 | 6 | object Hello extends IOApp.Simple { 7 | 8 | def sleepPrint(word: String, name: String, rand: Random[IO]) = 9 | for { 10 | delay <- rand.betweenInt(200, 700) 11 | _ <- IO.sleep(delay.millis) 12 | _ <- IO.println(s"$word, $name") 13 | } yield () 14 | 15 | val run = 16 | for { 17 | rand <- Random.scalaUtilRandom[IO] 18 | 19 | // try uncommenting first one locally! Scastie doesn't like System.in 20 | // name <- IO.print("Enter your name: ") >> IO.readLine 21 | name <- IO.pure("Daniel") 22 | 23 | english <- sleepPrint("Hello", name, rand).foreverM.start 24 | french <- sleepPrint("Bonjour", name, rand).foreverM.start 25 | spanish <- sleepPrint("Hola", name, rand).foreverM.start 26 | 27 | _ <- IO.sleep(5.seconds) 28 | _ <- english.cancel >> french.cancel >> spanish.cancel 29 | } yield () 30 | } 31 | -------------------------------------------------------------------------------- /scripts/make-release-prs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | IFS=$'\n\t' 5 | 6 | cd "$(dirname $0)/.." 7 | primary_base="$(pwd)" 8 | 9 | if [[ $# -ne 2 ]] || [[ "$1" == "--help" ]]; then 10 | echo "usage: $0 old-tag new-tag" 11 | exit 1 12 | fi 13 | 14 | old_version="${1#v}" 15 | new_version="${2#v}" 16 | 17 | minor_base=series/$(echo $new_version | sed -E 's/([0-9]+).([0-9]+).[0-9]+/\1.\2.x/') 18 | major_base=series/$(echo $new_version | sed -E 's/([0-9]+).[0-9]+.[0-9]+/\1.x/') 19 | minor_branch="release/$new_version-minor" 20 | major_branch="release/$new_version-major" 21 | 22 | cd "$(mktemp -d)" 23 | gh repo clone typelevel/cats-effect 24 | cd 'cats-effect' 25 | 26 | git checkout -b $minor_branch origin/$minor_base 27 | "$primary_base/scripts/update-versions.sh" --base . $old_version $new_version 28 | git commit -a -m "Update versions for $new_version" 29 | git push origin $minor_branch 30 | 31 | gh pr create \ 32 | --fill \ 33 | --base $minor_base \ 34 | --repo typelevel/cats-effect \ 35 | --head typelevel:$minor_branch \ 36 | --label ':robot:' 37 | 38 | git checkout -b $major_branch 39 | git push origin $major_branch 40 | 41 | gh pr create \ 42 | --title "Merge changes from $new_version into $major_base" \ 43 | --body '' \ 44 | --base $major_base \ 45 | --repo typelevel/cats-effect \ 46 | --head typelevel:$major_branch \ 47 | --label ':robot:' 48 | -------------------------------------------------------------------------------- /scripts/post-release-discord.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | IFS=$'\n\t' 5 | 6 | if [[ $# -ne 1 ]] || [[ "$1" == "--help" ]]; then 7 | echo "usage: $0 new-tag" 8 | exit 1 9 | fi 10 | 11 | # defunct example: 12 | # 13 | # export DISCORD_WEBHOOK_URL='https://discord.com/api/webhooks/1122248098014564483/qv_hfoMpexcTjX_8FX23uisvpqrt_N_UD8VtYFLzUo8ROthEWk5cqECQPB3OCJ9MNUxB' 14 | # 15 | # this url should be considered a secret and handled with appropriate care 16 | 17 | data="{\"content\":\"https://github.com/typelevel/cats-effect/releases/tag/$1\"}" 18 | 19 | exec curl -H "Content-Type: application/json" -X POST -d "$data" "$DISCORD_WEBHOOK_URL" 20 | -------------------------------------------------------------------------------- /scripts/update-versions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | IFS=$'\n\t' 5 | 6 | if [[ $# -lt 2 ]] || [[ "$1" == "--help" ]]; then 7 | echo "usage: $0 old-tag new-tag" 8 | exit 1 9 | fi 10 | 11 | if [[ "$1" == "--base" ]]; then 12 | shift 13 | cd "$1" 14 | shift 15 | else 16 | cd "$(dirname $0)/.." 17 | fi 18 | 19 | old_version="${1#v}" 20 | new_version="${2#v}" 21 | 22 | # perl is ironically more portable than sed because of GNU/BSD differences 23 | # the quote reduce the false positive rate 24 | find . -type f -name '*.md' -exec perl -pi -e "s/\"$old_version\"/\"$new_version\"/g" {} \; 25 | find . -type f -name '*.md' -exec perl -pi -e "s/\\*\\*$old_version\\*\\*/\\*\\*$new_version\\*\\*/g" {} \; 26 | find . -type f -name '*.md' -exec perl -pi -e "s/:$old_version/:$new_version/g" {} \; 27 | -------------------------------------------------------------------------------- /site-docs/sidebars-todo.json: -------------------------------------------------------------------------------- 1 | // https://github.com/typelevel/cats-effect/issues/1715 2 | { 3 | "docs": { 4 | "Overview": [ 5 | // TODO IO Documentation https://github.com/typelevel/cats-effect/pull/1877 6 | // TODO performance https://github.com/typelevel/cats-effect/issues/1107 7 | ], 8 | "Typeclasses": [ 9 | // Document the behavior changes to bracket/guarantee between CE2 and CE3 10 | // https://github.com/typelevel/cats-effect/issues/2242 11 | ], 12 | "Standard Library": [ 13 | // TODO std/console 14 | ], 15 | /* TODOs 16 | "Leveling Up": [ 17 | // this is where we talk about patterns and best practices, tagless, etc 18 | // https://github.com/typelevel/cats-effect/issues/1143 19 | ], 20 | "Ecosystem": [ 21 | // let's throw some pages in here focused on use-cases, like HTTP clients, Redis things, etc 22 | // https://github.com/typelevel/cats-effect/issues/1177 23 | // https://github.com/typelevel/cats-effect/pull/1809 24 | ], 25 | "Resources" :[ 26 | // training, posts, video, etc 27 | // https://github.com/typelevel/cats-effect/issues/1098 28 | ], 29 | "Scaling and Tuning": [ 30 | // some advanced advice for operating Cats Effect services at scale 31 | // https://github.com/typelevel/cats-effect/issues/1127 32 | ] 33 | */ 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /site-docs/sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": { 3 | "Overview": [ 4 | "getting-started", 5 | "concepts", 6 | "tutorial", 7 | "recipes", 8 | "faq", 9 | "migration-guide", 10 | "third-party-resources" 11 | ], 12 | "Core Runtime": [ 13 | "core/test-runtime", 14 | "core/fiber-dumps", 15 | "tracing", 16 | "thread-model", 17 | "schedulers", 18 | "core/starvation-and-tuning", 19 | "core/io-runtime-config", 20 | "core/native-image", 21 | "core/scala-native", 22 | "core/jlink", 23 | "core/io-local" 24 | ], 25 | "Typeclasses": [ 26 | "typeclasses", 27 | "typeclasses/monadcancel", 28 | "typeclasses/spawn", 29 | "typeclasses/unique", 30 | "typeclasses/clock", 31 | "typeclasses/concurrent", 32 | "typeclasses/temporal", 33 | "typeclasses/sync", 34 | "typeclasses/async" 35 | ], 36 | "Standard Library": [ 37 | "std/atomic-cell", 38 | "std/backpressure", 39 | "std/console", 40 | "std/countdown-latch", 41 | "std/cyclic-barrier", 42 | "std/deferred", 43 | "std/dequeue", 44 | "std/dispatcher", 45 | "std/env", 46 | "std/hotswap", 47 | "std/mapref", 48 | "std/mutex", 49 | "std/pqueue", 50 | "std/queue", 51 | "std/random", 52 | "std/ref", 53 | "std/resource", 54 | "std/semaphore", 55 | "std/supervisor", 56 | "std/async-await" 57 | ] 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /std/js-native/src/main/scala/cats/effect/std/UUIDGenCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Scala.js (https://www.scala-js.org/) 19 | * 20 | * Copyright EPFL. 21 | * 22 | * Licensed under Apache License 2.0 23 | * (https://www.apache.org/licenses/LICENSE-2.0). 24 | * 25 | * See the NOTICE file distributed with this work for 26 | * additional information regarding copyright ownership. 27 | */ 28 | 29 | package cats.effect.std 30 | 31 | import cats.effect.kernel.Sync 32 | 33 | private[std] trait UUIDGenCompanionPlatform extends UUIDGenCompanionPlatformLowPriority 34 | 35 | private[std] trait UUIDGenCompanionPlatformLowPriority { 36 | 37 | @deprecated( 38 | "Put an implicit `SecureRandom.javaSecuritySecureRandom` into scope to get a more efficient `UUIDGen`, or directly call `UUIDGen.fromSecureRandom`", 39 | "3.6.0" 40 | ) 41 | implicit def fromSync[F[_]](implicit ev: Sync[F]): UUIDGen[F] = { 42 | UUIDGen.fromSecureRandom[F](using ev, SecureRandom.unsafeJavaSecuritySecureRandom()) 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /std/js/src/main/scala/cats/effect/std/DispatcherPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | import scala.scalajs.js 20 | 21 | private[std] trait DispatcherPlatform[F[_]] { this: Dispatcher[F] => 22 | 23 | /** 24 | * Submits an effect to be executed, returning a `Promise` that holds the result of its 25 | * evaluation. 26 | */ 27 | def unsafeToPromise[A](fa: F[A]): js.Promise[A] = 28 | new js.Promise[A]((resolve, reject) => 29 | unsafeRunAsync(fa) { 30 | case Left(js.JavaScriptException(e)) => 31 | reject(e) 32 | () 33 | 34 | case Left(e) => 35 | reject(e) 36 | () 37 | 38 | case Right(value) => 39 | resolve(value) 40 | () 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /std/js/src/main/scala/cats/effect/std/EnvCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | import cats.data.OptionT 20 | import cats.effect.kernel.Sync 21 | 22 | import scala.collection.immutable.Iterable 23 | import scala.scalajs.js 24 | import scala.util.Try 25 | 26 | private[std] class EnvCompanionPlatform { 27 | private[std] final class SyncEnv[F[_]](implicit F: Sync[F]) extends Env[F] { 28 | def get(name: String): F[Option[String]] = 29 | OptionT(F.delay(processEnv.get(name))).collect { 30 | case value: String => value // JavaScript. 'nuff said 31 | }.value 32 | 33 | def entries: F[Iterable[(String, String)]] = 34 | F.delay(processEnv.collect { case (name, value: String) => name -> value }.toList) 35 | 36 | private def processEnv = 37 | Try(js.Dynamic.global.process.env.asInstanceOf[js.Dictionary[Any]]) 38 | .getOrElse(js.Dictionary.empty) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /std/js/src/main/scala/cats/effect/std/MapRefCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | private[std] trait MapRefCompanionPlatform {} 20 | -------------------------------------------------------------------------------- /std/jvm-native/src/main/scala/cats/effect/std/EnvCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | import cats.effect.kernel.Sync 20 | 21 | import scala.collection.immutable.Iterable 22 | 23 | private[std] class EnvCompanionPlatform { 24 | private[std] final class SyncEnv[F[_]](implicit F: Sync[F]) extends Env[F] { 25 | 26 | def get(name: String): F[Option[String]] = 27 | F.delay(Option(System.getenv(name))) // sys.env copies the entire env into a Map 28 | 29 | def entries: F[Iterable[(String, String)]] = F.delay(sys.env) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /std/jvm-native/src/main/scala/cats/effect/std/MapRefCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | import cats.effect.kernel._ 20 | import cats.syntax.all._ 21 | 22 | private[std] trait MapRefCompanionPlatform { 23 | 24 | def inScalaConcurrentTrieMap[G[_]: Sync, F[_]: Sync, K, V]: G[MapRef[F, K, Option[V]]] = 25 | Sync[G] 26 | .delay(scala.collection.concurrent.TrieMap.empty[K, V]) 27 | .map(MapRef.fromScalaConcurrentMap[F, K, V](_)) 28 | 29 | def ofScalaConcurrentTrieMap[F[_]: Sync, K, V]: F[MapRef[F, K, Option[V]]] = 30 | Sync[F] 31 | .delay(scala.collection.concurrent.TrieMap.empty[K, V]) 32 | .map(MapRef.fromScalaConcurrentMap[F, K, V](_)) 33 | 34 | } 35 | -------------------------------------------------------------------------------- /std/jvm/src/main/scala/cats/effect/std/UUIDGenCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | import cats.effect.kernel.Sync 20 | 21 | import java.util.UUID 22 | 23 | private[std] trait UUIDGenCompanionPlatform extends UUIDGenCompanionPlatformLowPriority 24 | 25 | private[std] trait UUIDGenCompanionPlatformLowPriority { 26 | 27 | @deprecated( 28 | "Put an implicit `SecureRandom.javaSecuritySecureRandom` into scope to get a more efficient `UUIDGen`, or directly call `UUIDGen.fromSecureRandom`", 29 | "3.6.0" 30 | ) 31 | implicit def fromSync[F[_]](implicit ev: Sync[F]): UUIDGen[F] = new UUIDGen[F] { 32 | override final val randomUUID: F[UUID] = 33 | ev.blocking(UUID.randomUUID()) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /std/native/src/main/scala/cats/effect/std/ConsoleCompanionPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | import cats.effect.kernel.Sync 20 | 21 | private[std] trait ConsoleCompanionPlatform extends ConsoleCompanionCrossPlatform { 22 | 23 | /** 24 | * Constructs a `Console` instance for `F` data types that are [[cats.effect.kernel.Sync]]. 25 | */ 26 | def make[F[_]](implicit F: Sync[F]): Console[F] = 27 | new SyncConsole[F] 28 | 29 | } 30 | -------------------------------------------------------------------------------- /std/shared/src/main/scala/cats/effect/std/FailureSignal.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | private object FailureSignal extends RuntimeException with scala.util.control.NoStackTrace 20 | -------------------------------------------------------------------------------- /std/shared/src/main/scala/cats/effect/std/syntax/AllSyntax.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package std.syntax 19 | 20 | trait AllSyntax extends BackpressureSyntax with SupervisorSyntax 21 | -------------------------------------------------------------------------------- /std/shared/src/main/scala/cats/effect/std/syntax/BackpressureSyntax.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std.syntax 18 | 19 | import cats.effect.std.Backpressure 20 | 21 | trait BackpressureSyntax { 22 | implicit def backpressureOps[F[_], A](wrapped: F[A]): BackpressureOps[F, A] = 23 | new BackpressureOps(wrapped) 24 | } 25 | 26 | final class BackpressureOps[F[_], A] private[syntax] (private[syntax] val wrapped: F[A]) 27 | extends AnyVal { 28 | def metered(backpressure: Backpressure[F]): F[Option[A]] = 29 | backpressure.metered(wrapped) 30 | } 31 | -------------------------------------------------------------------------------- /std/shared/src/main/scala/cats/effect/std/syntax/SupervisorSyntax.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std.syntax 18 | 19 | import cats.effect.kernel.Fiber 20 | import cats.effect.std.Supervisor 21 | 22 | trait SupervisorSyntax { 23 | implicit def supervisorOps[F[_], A](wrapped: F[A]): SupervisorOps[F, A] = 24 | new SupervisorOps(wrapped) 25 | } 26 | 27 | final class SupervisorOps[F[_], A] private[syntax] (private[syntax] val wrapped: F[A]) 28 | extends AnyVal { 29 | def supervise(supervisor: Supervisor[F]): F[Fiber[F, Throwable, A]] = 30 | supervisor.supervise(wrapped) 31 | } 32 | -------------------------------------------------------------------------------- /std/shared/src/main/scala/cats/effect/std/syntax/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | package object syntax { 20 | 21 | object all extends AllSyntax 22 | 23 | object supervisor extends SupervisorSyntax 24 | 25 | } 26 | -------------------------------------------------------------------------------- /std/shared/src/main/scala/cats/effect/std/unsafe/BoundedQueueSink.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats 18 | package effect 19 | package std 20 | package unsafe 21 | 22 | trait BoundedQueueSink[F[_], A] extends QueueSink[F, A] { 23 | def unsafeTryOffer(a: A): Boolean 24 | } 25 | 26 | object BoundedQueueSink { 27 | implicit def catsContravariantForBoundedQueueSink[F[_]] 28 | : Contravariant[BoundedQueueSink[F, *]] = 29 | new Contravariant[BoundedQueueSink[F, *]] { 30 | override def contramap[A, B](fa: BoundedQueueSink[F, A])( 31 | f: B => A): BoundedQueueSink[F, B] = 32 | new BoundedQueueSink[F, B] { 33 | override def unsafeTryOffer(b: B): Boolean = 34 | fa.unsafeTryOffer(f(b)) 35 | override def offer(b: B): F[Unit] = 36 | fa.offer(f(b)) 37 | override def tryOffer(b: B): F[Boolean] = 38 | fa.tryOffer(f(b)) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /std/shared/src/main/scala/cats/effect/std/unsafe/UnboundedQueueSink.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats 18 | package effect 19 | package std 20 | package unsafe 21 | 22 | trait UnboundedQueueSink[F[_], A] extends QueueSink[F, A] with BoundedQueueSink[F, A] { 23 | def unsafeOffer(a: A): Unit 24 | 25 | def unsafeTryOffer(a: A): Boolean = { 26 | unsafeOffer(a) 27 | true 28 | } 29 | } 30 | 31 | object UnboundedQueueSink { 32 | implicit def catsContravariantForUnboundedQueueSink[F[_]] 33 | : Contravariant[UnboundedQueueSink[F, *]] = 34 | new Contravariant[UnboundedQueueSink[F, *]] { 35 | override def contramap[A, B](fa: UnboundedQueueSink[F, A])( 36 | f: B => A): UnboundedQueueSink[F, B] = 37 | new UnboundedQueueSink[F, B] { 38 | override def unsafeOffer(b: B): Unit = 39 | fa.unsafeOffer(f(b)) 40 | override def offer(b: B): F[Unit] = 41 | fa.offer(f(b)) 42 | override def tryOffer(b: B): F[Boolean] = 43 | fa.tryOffer(f(b)) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /std/shared/src/test/scala/cats/effect/std/SyntaxSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.std 18 | 19 | import cats.effect.kernel.{Async, Concurrent, Deferred, GenConcurrent, Ref, Sync} 20 | 21 | import munit.FunSuite 22 | 23 | class SyntaxSuite extends FunSuite { 24 | 25 | test("concurrent data structure construction syntax") {} 26 | 27 | def async[F[_]: Async] = { 28 | Ref.of[F, String]("foo") 29 | Ref.empty[F, String] 30 | Ref[F].of(15) 31 | Ref[F].empty[String] 32 | Deferred[F, Unit] 33 | Semaphore[F](15) 34 | } 35 | 36 | def genConcurrent[F[_]](implicit F: GenConcurrent[F, ?]) = { 37 | Ref.of[F, Int](0) 38 | Deferred[F, Unit] 39 | } 40 | 41 | def sync[F[_]](implicit F: Sync[F]) = { 42 | Ref.of[F, Int](0) 43 | } 44 | 45 | def preciseConstraints[F[_]: Ref.Make] = { 46 | Ref.of[F, String]("foo") 47 | Ref[F].of(15) 48 | Ref.empty[F, String] 49 | Ref[F].empty[String] 50 | } 51 | 52 | def semaphoreIsDeriveable[F[_]](implicit F: Concurrent[F]) = 53 | Semaphore[F](11) 54 | } 55 | -------------------------------------------------------------------------------- /testkit/shared/src/main/scala/cats/effect/testkit/TestException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.testkit 18 | 19 | final case class TestException(i: Int) extends RuntimeException 20 | -------------------------------------------------------------------------------- /testkit/shared/src/main/scala/cats/effect/testkit/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | package object testkit { 20 | type TestContext = cats.effect.kernel.testkit.TestContext 21 | val TestContext = cats.effect.kernel.testkit.TestContext 22 | } 23 | -------------------------------------------------------------------------------- /tests/js/src/main/scala/cats/effect/DetectPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import scala.scalajs.js 20 | import scala.util.Try 21 | 22 | trait DetectPlatform { 23 | 24 | def isWSL: Boolean = { 25 | val t = Try { 26 | val os = js.Dynamic.global.require("os") 27 | val process = js.Dynamic.global.process 28 | 29 | val isLinux = process.platform.asInstanceOf[String].toLowerCase == "linux" 30 | val ms = os.release().asInstanceOf[String].toLowerCase.contains("microsoft") 31 | 32 | isLinux && ms // this mis-identifies docker on Windows, which should be considered unsupported for the CE build 33 | } 34 | 35 | t.getOrElse(false) 36 | } 37 | 38 | def isJS: Boolean = true 39 | def isJVM: Boolean = false 40 | def isNative: Boolean = false 41 | } 42 | -------------------------------------------------------------------------------- /tests/js/src/test/scala/cats/effect/ContSpecBasePlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | trait ContSpecBasePlatform { this: ContSpecBase => 20 | val iterations = 1 21 | } 22 | -------------------------------------------------------------------------------- /tests/js/src/test/scala/cats/effect/RunnersPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import cats.effect.unsafe.IORuntime 20 | 21 | trait RunnersPlatform { 22 | protected def runtime(): IORuntime = IORuntime.global 23 | } 24 | -------------------------------------------------------------------------------- /tests/js/src/test/scala/cats/effect/SyncIOPlatformSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | trait SyncIOPlatformSuite { self: BaseSuite => 20 | def platformTests() = { 21 | 22 | testUnit("realTimeDate should return an Instant constructed from realTime") { 23 | // Unfortunately since SyncIO doesn't rely on a controllable 24 | // time source, this is the best I can do 25 | val op = for { 26 | realTime <- SyncIO.realTime 27 | jsDate <- SyncIO.realTimeDate 28 | } yield (jsDate.getTime().toLong - realTime.toMillis) <= 30 29 | 30 | assertCompleteAsSync(op, true) 31 | } 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /tests/js/src/test/scala/cats/effect/exports.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import scala.scalajs.js 20 | import scala.scalajs.js.annotation._ 21 | 22 | // we don't care about this object, but we want to run its initializer 23 | @JSExportTopLevel("dummy") 24 | object exports extends js.Object { 25 | if (js.typeOf(js.Dynamic.global.process) == "undefined") { 26 | js.special.fileLevelThis.asInstanceOf[js.Dynamic].process = js.Object() 27 | if (js.typeOf(js.Dynamic.global.process.env) == "undefined") 28 | js.Dynamic.global.process.env = js.Object() 29 | js.Dynamic.global.process.env.CATS_EFFECT_TRACING_MODE = "cached" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/js/src/test/scala/cats/effect/std/ConsoleJSSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package std 19 | 20 | class ConsoleJSSuite extends BaseSuite { 21 | 22 | real("work in any JS environment") { 23 | Console[IO].println("printing") *> Console[IO].errorln("erroring") 24 | } 25 | real("println should not hang for large strings") { 26 | Console[IO].println("foo" * 10000) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /tests/jvm-native/src/main/scala/catseffect/examplesjvmnative.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package catseffect 18 | 19 | import cats.effect.{ExitCode, IO, IOApp} 20 | 21 | import java.io.{File, FileWriter} 22 | 23 | package examples { 24 | object Finalizers extends IOApp { 25 | 26 | def writeToFile(string: String, file: File): IO[Unit] = 27 | IO(new FileWriter(file)).bracket { writer => IO(writer.write(string)) }(writer => 28 | IO(writer.close())) 29 | 30 | def run(args: List[String]): IO[ExitCode] = 31 | (IO(println("Started")) >> IO.never) 32 | .onCancel(writeToFile("canceled", new File(args.head))) 33 | .as(ExitCode.Success) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/jvm-native/src/test/scala/cats/effect/ContSpecBasePlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | trait ContSpecBasePlatform { this: ContSpecBase => 20 | val iterations = 100000 21 | } 22 | -------------------------------------------------------------------------------- /tests/jvm-native/src/test/scala/cats/effect/SyncIOPlatformSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | trait SyncIOPlatformSuite { self: BaseSuite => 20 | def platformTests() = { 21 | 22 | testUnit("realTimeInstant should return an Instant constructed from realTime") { 23 | // Unfortunately since SyncIO doesn't use on a controllable 24 | // clock source, so a diff best we can do 25 | val op = for { 26 | realTime <- SyncIO.realTime 27 | now <- SyncIO.realTimeInstant 28 | } yield (now.toEpochMilli - realTime.toMillis) <= 10000 29 | 30 | assertCompleteAsSync(op, true) 31 | } 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /tests/jvm/src/test/resources/readline-test.ISO-8859-1.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vivamus at augue eget arcu. Viverra adipiscing at in tellus integer feugiat scelerisque varius. Posuere sollicitudin aliquam ultrices sagittis orci a scelerisque purus semper. Suspendisse potenti nullam ac tortor vitae. Dui accumsan sit amet nulla facilisi. In est ante in nibh mauris cursus mattis. Eu augue ut lectus arcu bibendum at varius vel. Laoreet sit amet cursus sit amet dictum. Iaculis at erat pellentesque adipiscing commodo elit at imperdiet dui. Cras semper auctor neque vitae tempus quam pellentesque nec nam. Dignissim convallis aenean et tortor at risus viverra adipiscing. Urna et pharetra pharetra massa. Eleifend quam adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus. Sagittis purus sit amet volutpat consequat mauris nunc congue. 2 | 3 | ISO-8859-1 does not support emojis. 4 | 5 | ISO-8859-1 does not support Cyrillic characters. -------------------------------------------------------------------------------- /tests/jvm/src/test/resources/readline-test.US-ASCII.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vivamus at augue eget arcu. Viverra adipiscing at in tellus integer feugiat scelerisque varius. Posuere sollicitudin aliquam ultrices sagittis orci a scelerisque purus semper. Suspendisse potenti nullam ac tortor vitae. Dui accumsan sit amet nulla facilisi. In est ante in nibh mauris cursus mattis. Eu augue ut lectus arcu bibendum at varius vel. Laoreet sit amet cursus sit amet dictum. Iaculis at erat pellentesque adipiscing commodo elit at imperdiet dui. Cras semper auctor neque vitae tempus quam pellentesque nec nam. Dignissim convallis aenean et tortor at risus viverra adipiscing. Urna et pharetra pharetra massa. Eleifend quam adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus. Sagittis purus sit amet volutpat consequat mauris nunc congue. 2 | 3 | US-ASCII does not support emojis. 4 | 5 | US-ASCII does not support Cyrillic characters. -------------------------------------------------------------------------------- /tests/jvm/src/test/resources/readline-test.UTF-16.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typelevel/cats-effect/768668a57fe8f8cef2bd6ec61d311da9a7a2629b/tests/jvm/src/test/resources/readline-test.UTF-16.txt -------------------------------------------------------------------------------- /tests/jvm/src/test/resources/readline-test.UTF-16BE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typelevel/cats-effect/768668a57fe8f8cef2bd6ec61d311da9a7a2629b/tests/jvm/src/test/resources/readline-test.UTF-16BE.txt -------------------------------------------------------------------------------- /tests/jvm/src/test/resources/readline-test.UTF-16LE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typelevel/cats-effect/768668a57fe8f8cef2bd6ec61d311da9a7a2629b/tests/jvm/src/test/resources/readline-test.UTF-16LE.txt -------------------------------------------------------------------------------- /tests/jvm/src/test/resources/readline-test.UTF-8.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vivamus at augue eget arcu. Viverra adipiscing at in tellus integer feugiat scelerisque varius. Posuere sollicitudin aliquam ultrices sagittis orci a scelerisque purus semper. Suspendisse potenti nullam ac tortor vitae. Dui accumsan sit amet nulla facilisi. In est ante in nibh mauris cursus mattis. Eu augue ut lectus arcu bibendum at varius vel. Laoreet sit amet cursus sit amet dictum. Iaculis at erat pellentesque adipiscing commodo elit at imperdiet dui. Cras semper auctor neque vitae tempus quam pellentesque nec nam. Dignissim convallis aenean et tortor at risus viverra adipiscing. Urna et pharetra pharetra massa. Eleifend quam adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus. Sagittis purus sit amet volutpat consequat mauris nunc congue. 2 | 3 | UTF-8 emojis for good measure: 4 | 🤷🏾‍♂️🐈📦🚀 5 | 6 | UTF-8 non-latin characters: 7 | Поздрав. -------------------------------------------------------------------------------- /tests/jvm/src/test/scala/cats/effect/DetectPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | trait DetectPlatform { 20 | def isWSL: Boolean = System.getProperty("os.version").contains("-WSL") 21 | def isJS: Boolean = false 22 | def isJVM: Boolean = true 23 | def isNative: Boolean = false 24 | 25 | def javaMajorVersion: Int = 26 | System.getProperty("java.version").stripPrefix("1.").takeWhile(_.isDigit).toInt 27 | } 28 | -------------------------------------------------------------------------------- /tests/jvm/src/test/scala/cats/effect/ParasiticECSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | import cats.effect.testkit.TestInstances 20 | import cats.syntax.all._ 21 | 22 | import org.scalacheck.Arbitrary 23 | 24 | import scala.concurrent.duration._ 25 | 26 | class ParasiticECSuite extends BaseSuite with TestInstances { 27 | 28 | override def executionTimeout: FiniteDuration = super.executionTimeout * 3 29 | 30 | real("evaluate fibers correctly in presence of a parasitic execution context") { 31 | val test = { 32 | implicit val ticker = Ticker() 33 | 34 | IO(implicitly[Arbitrary[IO[Int]]].arbitrary.sample.get).flatMap { io => 35 | IO.delay(io.eqv(io)) 36 | } 37 | } 38 | 39 | val iterations = 15000 40 | 41 | List.fill(iterations)(test).sequence.map(_.count(identity)).flatMap { c => 42 | IO { 43 | assertEquals(c, iterations) 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/jvm/src/test/scala/cats/effect/unsafe/DrainBatchSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package unsafe 19 | 20 | import cats.effect.std.Queue 21 | 22 | class DrainBatchSuite extends BaseSuite { 23 | 24 | real("work correctly in the presence of concurrent stealers") { 25 | val iterations = 500000 26 | 27 | def catsEffectRepeat[A](n: Int)(io: IO[A]): IO[A] = 28 | if (n <= 1) io 29 | else io.flatMap(_ => catsEffectRepeat(n - 1)(io)) 30 | 31 | def iterate(deferred: Deferred[IO, Unit], n: Int): IO[Any] = 32 | for { 33 | ref <- IO.ref(n) 34 | queue <- Queue.bounded[IO, Unit](1) 35 | effect = queue.offer(()).start >> 36 | queue.take >> 37 | ref.modify(n => (n - 1, if (n == 1) deferred.complete(()) else IO.unit)).flatten 38 | _ <- catsEffectRepeat(iterations)(effect.start) 39 | } yield () 40 | 41 | for { 42 | deferred <- IO.deferred[Unit] 43 | _ <- iterate(deferred, iterations).start 44 | _ <- deferred.get 45 | } yield () 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /tests/jvm/src/test/scala/cats/effect/unsafe/IOLocalsSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package unsafe 19 | 20 | class IOLocalsSuite extends BaseSuite { 21 | 22 | real("return a default value") { 23 | IOLocal(42).flatMap(local => IO(local.unsafeThreadLocal().get())).map(assertEquals(_, 42)) 24 | } 25 | 26 | real("return a set value") { 27 | for { 28 | local <- IOLocal(42) 29 | threadLocal <- IO(local.unsafeThreadLocal()) 30 | _ <- local.set(24) 31 | got <- IO(threadLocal.get()) 32 | } yield assertEquals(got, 24) 33 | } 34 | 35 | real("unsafely set") { 36 | IOLocal(42).flatMap(local => 37 | IO(local.unsafeThreadLocal().set(24)) *> local.get.map(assertEquals(_, 24))) 38 | } 39 | 40 | real("unsafely reset") { 41 | for { 42 | local <- IOLocal(42) 43 | threadLocal <- IO(local.unsafeThreadLocal()) 44 | _ <- local.set(24) 45 | _ <- IO(threadLocal.remove()) 46 | got <- local.get 47 | } yield assertEquals(got, 42) 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /tests/native/src/test/scala/cats/effect/DetectPlatform.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | trait DetectPlatform { 20 | def isWSL: Boolean = System.getProperty("os.version").contains("-WSL") 21 | def isJS: Boolean = false 22 | def isJVM: Boolean = false 23 | def isNative: Boolean = true 24 | } 25 | -------------------------------------------------------------------------------- /tests/native/src/test/scala/cats/effect/IOPlatformSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | trait IOPlatformSuite extends IOConcurrencySuite { this: BaseSuite => 20 | 21 | def platformTests() = { 22 | concurrencyTests() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/native/src/test/scala/cats/effect/unsafe/SchedulerSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package unsafe 19 | 20 | import scala.concurrent.duration._ 21 | 22 | class SchedulerSuite extends BaseSuite { 23 | 24 | real("use high-precision time") { 25 | for { 26 | start <- IO.realTime 27 | times <- IO.realTime.replicateA(100) 28 | deltas = times.map(_ - start) 29 | } yield assert(deltas.exists(_.toMicros % 1000 != 0)) 30 | } 31 | 32 | real("correctly calculate real time") { 33 | IO.realTime.product(IO(System.currentTimeMillis())).map { 34 | case (realTime, currentTime) => 35 | assert(realTime.toMillis - currentTime <= 1L) 36 | } 37 | } 38 | 39 | real("sleep for correct duration") { 40 | val duration = 1500.millis 41 | IO.sleep(duration).timed.map(r => assert(r._1 >= duration)) 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /tests/shared/src/main/scala/catseffect/RawApp.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package catseffect 18 | 19 | trait RawApp { 20 | def main(args: Array[String]): Unit 21 | } 22 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala-2.13+/not/cats/effect/IOCompilationSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package not.cats.effect // verifies scoping outside of CE 18 | 19 | import cats.effect.{BaseSuite, IO} 20 | 21 | class IOCompilationSpec extends BaseSuite { 22 | testUnit("Can use total function in PartialFunction IO.onError") { // compilation test 23 | IO.pure(5).onError(_ => IO.unit) 24 | () 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala-2.13+/not/cats/effect/IOParImplicitSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package not.cats.effect // verifies scoping outside of CE 18 | 19 | import cats.{Align, CommutativeApplicative} 20 | import cats.effect.{BaseSuite, IO} 21 | import cats.syntax.all._ 22 | 23 | class IOParImplicitSuite extends BaseSuite { 24 | 25 | testUnit("Can resolve CommutativeApplicative instance") { 26 | List(1, 2, 3).parUnorderedTraverse(_ => IO.unit) // compilation test 27 | () 28 | } 29 | 30 | testUnit("Can resolve IO.Par instances") { // compilation test 31 | Align[IO.Par] 32 | CommutativeApplicative[IO.Par] 33 | () 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/ExitCodeSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | class ExitCodeSuite extends BaseSuite { 20 | 21 | testUnit("ExitCode.unapply is exhaustive") { 22 | ExitCode(0) match { // if not, should be a fatal warning in CI 23 | case ExitCode(_) => assert(true) 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/IOMtlLocalSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats 18 | package effect 19 | 20 | import cats.mtl.Local 21 | import cats.mtl.laws.discipline._ 22 | 23 | import java.util.concurrent.CancellationException 24 | 25 | import munit.DisciplineSuite 26 | 27 | class IOMtlLocalSuite extends BaseSuite with DisciplineSuite { 28 | 29 | implicit val ticker: Ticker = Ticker() 30 | 31 | implicit val local: Local[IO, Int] = 32 | // Don't try this at home 33 | unsafeRun(IO.local(0)).fold( 34 | throw new CancellationException("canceled"), 35 | throw _, 36 | _.get 37 | ) 38 | 39 | checkAll("Local[IO, Int]", LocalTests[IO, Int].local[Int, Int]) 40 | } 41 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/ThunkSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | 19 | class ThunkSuite extends BaseSuite { 20 | 21 | testUnit("return the same function") { 22 | var i = 0 23 | val f = () => i += 1 24 | assertEquals(IO.delay(f()).asInstanceOf[IO.Delay[Unit]].thunk, f) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/std/ConsoleSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package std 19 | 20 | class ConsoleSuite extends BaseSuite { 21 | 22 | case class Foo(n: Int, b: Boolean) 23 | 24 | testUnit("select default Show.fromToString (IO)") { 25 | val _ = ( 26 | IO.print(Foo(1, true)), // compilation test 27 | IO.println(Foo(1, true)) // compilation test 28 | ) 29 | } 30 | 31 | testUnit("select default Show.fromToString (Console[IO])") { 32 | val _ = ( 33 | Console[IO].print(Foo(1, true)), // compilation test 34 | Console[IO].println(Foo(1, true)), // compilation test 35 | Console[IO].error(Foo(1, true)), // compilation test 36 | Console[IO].errorln(Foo(1, true)) // compilation test 37 | ) 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/std/EnvSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package std 19 | 20 | class EnvSuite extends BaseSuite { 21 | 22 | real("retrieve a variable from the environment") { 23 | Env[IO].get("HOME").flatMap(x => IO(assert(x.isDefined))) 24 | } 25 | real("return none for non-existent environment variable") { 26 | Env[IO].get("MADE_THIS_UP").flatMap(x => IO(assert(x.isEmpty))) 27 | } 28 | real("provide an iterable of all the things") { 29 | Env[IO].entries.flatMap(x => IO(assert(x.nonEmpty))) 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/std/SecureRandomSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package std 19 | 20 | class SecureRandomSuite extends BaseSuite { 21 | 22 | real("securely generate random bytes") { 23 | for { 24 | random1 <- SecureRandom.javaSecuritySecureRandom[IO] 25 | bytes1 <- random1.nextBytes(128) 26 | random2 <- SecureRandom.javaSecuritySecureRandom[IO](2) 27 | bytes2 <- random2.nextBytes(256) 28 | bytes3 <- random2.nextBytes(1024) 29 | } yield assert(bytes1.length == 128 && bytes2.length == 256 && bytes3.length == 1024) 30 | } 31 | 32 | real("overrides nextInt") { 33 | for { 34 | secureRandom <- SecureRandom.javaSecuritySecureRandom[IO] 35 | secureInts <- secureRandom.nextInt.replicateA(3) 36 | insecureRandom <- Random.scalaUtilRandomSeedInt[IO](0) 37 | insecureInts <- insecureRandom.nextInt.replicateA(3) 38 | } yield assert(secureInts != insecureInts) 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/std/SystemPropertiesSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package std 19 | 20 | class SystemPropertiesSuite extends BaseSuite { 21 | 22 | real("retrieve a property just set") { 23 | Random.javaUtilConcurrentThreadLocalRandom[IO].nextString(12).flatMap { key => 24 | SystemProperties[IO].set(key, "bar") *> 25 | SystemProperties[IO].get(key).flatMap(x => IO(assertEquals(x, Some("bar")))) 26 | } 27 | } 28 | real("return none for a non-existent property") { 29 | SystemProperties[IO].get("MADE_THIS_UP").flatMap(x => IO(assertEquals(x, None))) 30 | } 31 | real("clear") { 32 | Random.javaUtilConcurrentThreadLocalRandom[IO].nextString(12).flatMap { key => 33 | SystemProperties[IO].set(key, "bar") *> SystemProperties[IO].clear(key) *> 34 | SystemProperties[IO].get(key).flatMap(x => IO(assertEquals(x, None))) 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/std/UUIDGenSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package std 19 | 20 | class UUIDGenSuite extends BaseSuite { 21 | 22 | real("securely generate UUIDs") { 23 | for { 24 | left <- UUIDGen.randomUUID[IO] 25 | right <- UUIDGen.randomUUID[IO] 26 | } yield assert(left != right) 27 | } 28 | 29 | real("use the correct variant and version") { 30 | for { 31 | uuid <- UUIDGen.randomUUID[IO] 32 | } yield { 33 | assertEquals(uuid.variant, 2) 34 | assertEquals(uuid.version, 4) 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/unsafe/IORuntimeBuilderSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect 18 | package unsafe 19 | 20 | import munit.TestOptions 21 | 22 | class IORuntimeBuilderSuite extends BaseSuite with DetectPlatform { 23 | 24 | testUnit(("configure the failure reporter": TestOptions).ignoreNative) { 25 | var invoked = false 26 | val rt = IORuntime.builder().setFailureReporter(_ => invoked = true).build() 27 | rt.compute.reportFailure(new Exception) 28 | assert(invoked) 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /tests/shared/src/test/scala/cats/effect/unsafe/IORuntimeSuite.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Typelevel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cats.effect.unsafe 18 | 19 | import cats.effect.BaseSuite 20 | 21 | class IORuntimeSuite extends BaseSuite { 22 | 23 | testUnit("cleanup allRuntimes collection on shutdown") { 24 | val (defaultScheduler, closeScheduler) = Scheduler.createDefaultScheduler() 25 | 26 | val runtime = IORuntime(null, null, defaultScheduler, closeScheduler, IORuntimeConfig()) 27 | 28 | assertEquals(IORuntime.allRuntimes.unsafeHashtable().find(_ == runtime), Some(runtime)) 29 | 30 | val _ = runtime.shutdown() 31 | 32 | assertEquals(IORuntime.allRuntimes.unsafeHashtable().find(_ == runtime), None) 33 | } 34 | 35 | } 36 | --------------------------------------------------------------------------------