54    private ThreadSafeArray $fallbackLookup;
 
   59    private ThreadSafeArray $psr4Lookup;
 
   61    public function __construct(){
 
   62        $this->fallbackLookup = 
new ThreadSafeArray();
 
   63        $this->psr4Lookup = 
new ThreadSafeArray();
 
   66    protected function normalizePath(
string $path) : 
string{
 
   67        $parts = explode(
"://", $path, 2);
 
   68        if(count($parts) === 2){
 
   69            return $parts[0] . 
"://" . str_replace(
'/', DIRECTORY_SEPARATOR, $parts[1]);
 
   71        return str_replace(
'/', DIRECTORY_SEPARATOR, $parts[0]);
 
   74    public function addPath(
string $namespacePrefix, 
string $path, 
bool $prepend = 
false) : 
void{
 
   75        $path = $this->normalizePath($path);
 
   76        if($namespacePrefix === 
'' || $namespacePrefix === 
'\\'){
 
   77            $this->fallbackLookup->synchronized(
function() use ($path, $prepend) : 
void{
 
   81            $namespacePrefix = trim($namespacePrefix, 
'\\') . 
'\\';
 
   82            $this->psr4Lookup->synchronized(
function() use ($namespacePrefix, $path, $prepend) : 
void{
 
   83                $list = $this->psr4Lookup[$namespacePrefix] ?? 
null;
 
   85                    $list = $this->psr4Lookup[$namespacePrefix] = 
new ThreadSafeArray();
 
   99            foreach($entries as $removedEntry){
 
  100                $list[] = $removedEntry;
 
 
  115        while(($entry = $list->shift()) !== 
null){
 
 
  121    public function register(
bool $prepend = 
false) : bool{
 
  122        return spl_autoload_register(function(string $name) : void{
 
  123            $this->loadClass($name);
 
  131        $path = $this->findClass($name);
 
  134            if(!class_exists($name, 
false) && !interface_exists($name, 
false) && !trait_exists($name, 
false)){
 
  138            if(method_exists($name, 
"onClassLoaded") && (
new \ReflectionClass($name))->getMethod(
"onClassLoaded")->isStatic()){
 
  139                $name::onClassLoaded();
 
 
  152        $baseName = str_replace(
"\\", DIRECTORY_SEPARATOR, $name);
 
  154        foreach($this->fallbackLookup as $path){
 
  155            $filename = $path . DIRECTORY_SEPARATOR . $baseName . 
".php";
 
  156            if(file_exists($filename)){
 
  162        $logicalPathPsr4 = $baseName . 
".php";
 
  164        return $this->psr4Lookup->synchronized(
function() use ($name, $logicalPathPsr4) : ?
string{
 
  166            while(
false !== $lastPos = strrpos($subPath, 
'\\')){
 
  167                $subPath = substr($subPath, 0, $lastPos);
 
  168                $search = $subPath . 
'\\';
 
  169                $lookup = $this->psr4Lookup[$search] ?? 
null;
 
  170                if($lookup !== 
null){
 
  171                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
 
  172                    foreach($lookup as $dir){
 
  173                        if(file_exists($file = $dir . $pathEnd)){