| | | 1 | | <# |
| | | 2 | | .SYNOPSIS |
| | | 3 | | Converts collections to thread-safe equivalents. |
| | | 4 | | .DESCRIPTION |
| | | 5 | | This function takes various collection types (hashtables, arrays, dictionaries) |
| | | 6 | | and converts them into thread-safe versions suitable for use in multi-threaded |
| | | 7 | | or multi-runspace scenarios. |
| | | 8 | | .PARAMETER Value |
| | | 9 | | The input collection to convert. |
| | | 10 | | .EXAMPLE |
| | | 11 | | # Convert a hashtable to a thread-safe hashtable |
| | | 12 | | $ht = @{ Key1 = 'Value1'; Key2 = 'Value2' } |
| | | 13 | | $threadSafeHt = ConvertTo-KrThreadSafeValue -Value $ht |
| | | 14 | | .EXAMPLE |
| | | 15 | | # Convert an ArrayList to a thread-safe ArrayList |
| | | 16 | | $arrayList = [System.Collections.ArrayList]::new() |
| | | 17 | | $threadSafeArrayList = ConvertTo-KrThreadSafeValue -Value $arrayList |
| | | 18 | | .OUTPUTS |
| | | 19 | | Thread-safe collection equivalent of the input. If the input is not a collection, returns it unchanged. |
| | | 20 | | #> |
| | | 21 | | function ConvertTo-KrThreadSafeValue { |
| | | 22 | | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseOutputTypeCorrectly', '')] |
| | | 23 | | [CmdletBinding()] |
| | | 24 | | param( |
| | | 25 | | [Parameter(Mandatory)] |
| | | 26 | | [object]$Value |
| | | 27 | | ) |
| | | 28 | | |
| | 0 | 29 | | if ($null -eq $Value) { |
| | 0 | 30 | | return $null |
| | | 31 | | } |
| | | 32 | | |
| | | 33 | | # --- Hashtable (@{}) --- |
| | 0 | 34 | | if ($Value -is [hashtable]) { |
| | 0 | 35 | | return [hashtable]::Synchronized($Value) |
| | | 36 | | } |
| | | 37 | | |
| | | 38 | | # --- OrderedDictionary ([ordered]@{}) --- |
| | 0 | 39 | | if ($Value -is [System.Collections.Specialized.OrderedDictionary]) { |
| | | 40 | | # Copy into a normal hashtable and wrap |
| | 0 | 41 | | $ht = @{} |
| | 0 | 42 | | foreach ($entry in $Value.GetEnumerator()) { |
| | 0 | 43 | | $ht[$entry.Key] = $entry.Value |
| | | 44 | | } |
| | 0 | 45 | | return [hashtable]::Synchronized($ht) |
| | | 46 | | } |
| | | 47 | | |
| | | 48 | | # --- ArrayList --- |
| | 0 | 49 | | if ($Value -is [System.Collections.ArrayList]) { |
| | 0 | 50 | | return [System.Collections.ArrayList]::Synchronized($Value) |
| | | 51 | | } |
| | | 52 | | |
| | | 53 | | # --- Any other IDictionary (generic or not, but not handled above) --- |
| | 0 | 54 | | if ($Value -is [System.Collections.IDictionary]) { |
| | 0 | 55 | | $dict = [System.Collections.Concurrent.ConcurrentDictionary[object, object]]::new() |
| | 0 | 56 | | foreach ($entry in $Value.GetEnumerator()) { |
| | 0 | 57 | | $null = $dict.TryAdd($entry.Key, $entry.Value) |
| | | 58 | | } |
| | 0 | 59 | | return $dict |
| | | 60 | | } |
| | | 61 | | |
| | | 62 | | # --- Arrays: treat as immutable snapshots --- |
| | 0 | 63 | | if ($Value -is [Array]) { |
| | 0 | 64 | | return $Value |
| | | 65 | | } |
| | | 66 | | |
| | | 67 | | # --- PSCustomObject, scalars, etc.: just return as-is --- |
| | 0 | 68 | | return $Value |
| | | 69 | | } |