1 //===-- runtime/unit-map.cpp ------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "unit-map.h" 10 11 namespace Fortran::runtime::io { 12 13 ExternalFileUnit *UnitMap::LookUpForClose(int n) { 14 CriticalSection critical{lock_}; 15 Chain *previous{nullptr}; 16 int hash{Hash(n)}; 17 for (Chain *p{bucket_[hash].get()}; p; previous = p, p = p->next.get()) { 18 if (p->unit.unitNumber() == n) { 19 if (previous) { 20 previous->next.swap(p->next); 21 } else { 22 bucket_[hash].swap(p->next); 23 } 24 // p->next.get() == p at this point; the next swap pushes p on closing_ 25 closing_.swap(p->next); 26 return &p->unit; 27 } 28 } 29 return nullptr; 30 } 31 32 void UnitMap::DestroyClosed(ExternalFileUnit &unit) { 33 Chain *p{nullptr}; 34 { 35 CriticalSection critical{lock_}; 36 Chain *previous{nullptr}; 37 for (p = closing_.get(); p; previous = p, p = p->next.get()) { 38 if (&p->unit == &unit) { 39 if (previous) { 40 previous->next.swap(p->next); 41 } else { 42 closing_.swap(p->next); 43 } 44 break; 45 } 46 } 47 } 48 if (p) { 49 p->unit.~ExternalFileUnit(); 50 FreeMemory(p); 51 } 52 } 53 54 void UnitMap::CloseAll(IoErrorHandler &handler) { 55 CriticalSection critical{lock_}; 56 for (int j{0}; j < buckets_; ++j) { 57 while (Chain * p{bucket_[j].get()}) { 58 bucket_[j].swap(p->next); // pops p from head of list 59 p->unit.CloseUnit(CloseStatus::Keep, handler); 60 p->unit.~ExternalFileUnit(); 61 FreeMemory(p); 62 } 63 } 64 } 65 66 ExternalFileUnit &UnitMap::Create(int n, const Terminator &terminator) { 67 Chain &chain{New<Chain>{}(terminator, n)}; 68 chain.next.reset(&chain); 69 bucket_[Hash(n)].swap(chain.next); // pushes new node as list head 70 return chain.unit; 71 } 72 } // namespace Fortran::runtime::io 73