Примеры работы с ansible

Recap

Let’s now recap what we learned line by line and check our understanding.

  • Line 1: We import the Hook from React. It lets us keep local state in a function component.
  • Line 4: Inside the component, we declare a new state variable by calling the Hook. It returns a pair of values, to which we give names. We’re calling our variable because it holds the number of button clicks. We initialize it to zero by passing as the only argument. The second returned item is itself a function. It lets us update the so we’ll name it .
  • Line 9: When the user clicks, we call with a new value. React will then re-render the component, passing the new value to it.

This might seem like a lot to take in at first. Don’t rush it! If you’re lost in the explanation, look at the code above again and try to read it from top to bottom. We promise that once you try to “forget” how state works in classes, and look at this code with fresh eyes, it will make sense.

Tip: What Do Square Brackets Mean?

You might have noticed the square brackets when we declare a state variable:

The names on the left aren’t a part of the React API. You can name your own state variables:

This JavaScript syntax is called . It means that we’re making two new variables and , where is set to the first value returned by , and is the second. It is equivalent to this code:

When we declare a state variable with , it returns a pair — an array with two items. The first item is the current value, and the second is a function that lets us update it. Using and to access them is a bit confusing because they have a specific meaning. This is why we use array destructuring instead.

Tip: Using Multiple State Variables

Declaring state variables as a pair of is also handy because it lets us give different names to different state variables if we want to use more than one:

In the above component, we have , , and as local variables, and we can update them individually:

You don’t have to use many state variables. State variables can hold objects and arrays just fine, so you can still group related data together. However, unlike in a class, updating a state variable always replaces it instead of merging it.

We provide more recommendations on splitting independent state variables .

Promise wrapper

Adding to every request is quite a cumbersome task. Sometimes we can make our life easier by using event delegation, e.g. set handlers on the whole transactions, but is much more convenient.

Let’s use a thin promise wrapper https://github.com/jakearchibald/idb further in this chapter. It creates a global object with promisified IndexedDB methods.

Then, instead of we can write like this:

So we have all the sweet “plain async code” and “try…catch” stuff.

If we don’t catch an error, then it falls through, till the closest outer .

An uncaught error becomes an “unhandled promise rejection” event on object.

We can handle such errors like this:

As we already know, a transaction auto-commits as soon as the browser is done with the current code and microtasks. So if we put a macrotask like in the middle of a transaction, then the transaction won’t wait for it to finish. It just auto-commits. So the next request in it would fail.

For a promise wrapper and the situation is the same.

Here’s an example of in the middle of the transaction:

The next after fails with an “inactive transaction” error, because the transaction is already committed and closed at that time.

The workaround is the same as when working with native IndexedDB: either make a new transaction or just split things apart.

  1. Prepare the data and fetch all that’s needed first.
  2. Then save in the database.

Internally, the wrapper performs a native IndexedDB request, adding to it, and returns a promise that rejects/resolves with the result.

That works fine most of the time. The examples are at the lib page https://github.com/jakearchibald/idb.

In few rare cases, when we need the original object, we can access it as property of the promise:

Метки

3D шутер
Action
Adventure
Alawar Entertainment
casual games
CE
Collector’s Edition
Electronic Arts
Elephant Games
Nevosoft
RPG
Stalker
Stalker Shadow of Chernobyl
Игры для iOS
Коллекционное издание
ОП 2.1
Объединенный пак 2.1
Поиск предметов
РПГ
Сталкер
Сталкер прохождение
автосимулятор
аркада
игры для ПК
игры для девочек
игры на Андроид
казуальная игра
казуальные игры
многопользовательская
мультиплатформенная
однопользовательская
разное
ресторанный симулятор
симулятор
скачать игру
стратегия
тайм-менеджмент
тактический шутер
три в ряд
триврядка
шутер
шутер от первого лица
шутер от третьего лица
экономическая стратегия
экшен

The answer: They’re just queues

React , and does not make changes directly to the state object.

React , and create queues for React core to update the state object of a React component.

So the process to update React state is asynchronous for performance reasons. That’s why changes don’t feel immediate.

So how do you perform an action after state has changed?

First, if you’re looking to become a strong and elite React developer within just 11 modules, you might want to look into Wes Bos, Advanced React course for just $97.00 (30% off). Wouldn’t it be nice to learn how to create end-to-end applications in React to get a higher paying job? Wes Bos, Advanced React course will make you an elite React developer and will teach you the skillset for you to have the confidence to apply for React positions.

Click here to become a strong and elite React developer: Advanced React course.

Disclaimer: The three React course links are affiliate links where I may receive a small commission for at no cost to you if you choose to purchase a plan from a link on this page. However, these are merely the course I fully recommend when it comes to becoming a React expert.

Declaring a State Variable

In a class, we initialize the state to by setting to in the constructor:

In a function component, we have no , so we can’t assign or read . Instead, we call the Hook directly inside our component:

What does calling do? It declares a “state variable”. Our variable is called but we could call it anything else, like . This is a way to “preserve” some values between the function calls — is a new way to use the exact same capabilities that provides in a class. Normally, variables “disappear” when the function exits but state variables are preserved by React.

What do we pass to as an argument? The only argument to the Hook is the initial state. Unlike with classes, the state doesn’t have to be an object. We can keep a number or a string if that’s all we need. In our example, we just want a number for how many times the user clicked, so pass as initial state for our variable. (If we wanted to store two different values in state, we would call twice.)

What does return? It returns a pair of values: the current state and a function that updates it. This is why we write . This is similar to and in a class, except you get them in a pair. If you’re not familiar with the syntax we used, we’ll come back to it .

Now that we know what the Hook does, our example should make more sense:

We declare a state variable called , and set it to . React will remember its current value between re-renders, and provide the most recent one to our function. If we want to update the current , we can call .

Session State in ASP.NET Core

As I stated above, if you’re using ASP.NET Core 2.0 or earlier, you won’t see this problem. I’ll demonstrate the old «expected» behaviour using an ASP.NET Core 2.0, to show how people experiencing the issue typically expect session state to behave. Then I’ll create the equivalent app in ASP.NET Core 2.1, and show that session state no longer seems to work.

What is session state?

Session state is a feature that (https://docs.microsoft.com/en-us/previous-versions/ms178581(v=vs.140) in which you can store and retrieve values server-side for a user browsing your site. Session state was often used quite extensively in ASP.NET apps, but was problematic for various reasons, primarily performance and scalability.

Session state in ASP.NET Core is somewhat dialled back. You should think of it more like a per-user cache. From a technical point of view, session state in ASP.NET Core requires two separate parts:

  • A cookie. Used to assign a unique identifier (the session ID) to a user.
  • A distributed cache. Used to store items associated with a given session ID.

Where possible, I would avoid using session state if you can get away without it. There’s a around its usage that can easily bite you if you’re not aware of them. For example:

  • Sessions are per-browser, not per logged-in user
  • Session cookies (and so sessions) should be deleted when the browser session ends, but might not be.
  • If a session doesn’t have any values in it, it will be deleted, generating a new session ID
  • The GDPR issue described in this post!

That covers what session state is and how it works. In the next section I’ll create a small app that tracks which pages you’ve visited by storing a list in session state, and then displays the list on the home page.

Using session state in an ASP.NET Core 2.0 app

To demonstrate the change in behaviour related to the 2.0 to 2.1 upgrade, I’m going to start by building an ASP.NET Core 2.0 app. As I apparently still have a bazillion .NET Core SDKs installed on my machine, I’m going to use the 2.0 SDK (version number 2.1.202) to scaffold a 2.0 project template.

Start by creating a global.json to pin the SDK version in your app directory:

Then scaffold a new ASP.NET Core 2.0 MVC app using :

Session state is not configured by default, so you need to add the required services. Update in Startup.cs to add the session services. By default, ASP.NET Core will use an in-memory session store, which is fine for testing purposes, but will need to be updated for a production environment:

You also need to add the session middleware to your pipeline. Only middleware added after the session middleware will have a access to session state, so you typically add it just before the MVC middleware in :

For this simple (toy) example I’m going to retrieve and set a session value with each page view, using the session-key . As you browse between various pages, the session value will expand into a semicolon-separated list of action names. Update your to use the function, as shown below:

Finally, we’ll display the current value of the key in the homepage, Index.chstml:

If you run the application and browse around a few times, you’ll see the session action-list build up. In the example below I visited the Home page three times, the About page twice, and the Contact page once:

If you view the cookies associated with the page, you will see the cookie that holds an encrypted session ID. If you delete this cookie, you’ll see the value is reset, and the list is lost.

This is the behaviour most people expect with session state, so no problems there. The difficulties arise when you try the same thing using an ASP.NET Core 2.1 / 2.2 app.

OPTIONS

ipset 

COMMANDS

ipsetipset

n, create SETNAME TYPENAME [ CREATE-OPTIONS ]
Create a set identified with setname and specified type. The type may require
type specific options. If the
-exist
option is specified,
ipset
ignores the error otherwise raised when the same set (setname and create parameters
are identical) already exists.
add SETNAME ADD-ENTRY [ ADD-OPTIONS ]
Add a given entry to the set. If the
-exist
option is specified,
ipset
ignores if the entry already added to the set.
del SETNAME DEL-ENTRY [ DEL-OPTIONS ]
Delete an entry from a set. If the
-exist
option is specified and the entry is not in the set (maybe already expired),
then the command is ignored.
test SETNAME TEST-ENTRY [ TEST-OPTIONS ]
Test whether an entry is in a set or not. Exit status number is zero
if the tested entry is in the set and nonzero if it is missing from
the set.
x, destroy [ SETNAME ]
Destroy the specified set or all the sets if none is given.

If the set has got reference(s), nothing is done and no set destroyed.

list [ SETNAME ] [ OPTIONS ]
List the header data and the entries for the specified set, or for
all sets if none is given. The
-resolve
option can be used to force name lookups (which may be slow). When the
-sorted
option is given, the entries are listed/saved sorted (which may be slow).
The option
-output
can be used to control the format of the listing:
plain, save or xml.
(The default is
plain.)
If the option
-name
is specified, just the names of the existing sets are listed. If the option
-terse
is specified, just the set names and headers are listed. The output is printed
to stdout, the option
-file
can be used to specify a filename instead of stdout.
save [ SETNAME ]
Save the given set, or all sets if none is given
to stdout in a format that
restore
can read. The option
-file
can be used to specify a filename instead of stdout.
restore
Restore a saved session generated by
save.
The saved session can be fed from stdin or the option
-file
can be used to specify a filename instead of stdin.

Please note, existing sets and elements are not erased by
restore unless specified so in the restore file. All commands
are allowed in restore mode except list, help,
version, interactive mode and restore itself.

flush [ SETNAME ]
Flush all entries from the specified set or flush
all sets if none is given.
e, rename SETNAME-FROM SETNAME-TO
Rename a set. Set identified by
SETNAME-TO
must not exist.
w, swap SETNAME-FROM SETNAME-TO
Swap the content of two sets, or in another words,
exchange the name of two sets. The referred sets must exist and
compatible type of sets can be swapped only.
help [ TYPENAME ]
Print help and set type specific help if
TYPENAME
is specified.
version
Print program version.
If a dash is specified as command, then
ipset
enters a simple interactive mode and the commands are read from the standard input.
The interactive mode can be finished by entering the pseudo-command
quit.

OTHER OPTIONS

-!, -exist
Ignore errors when exactly the same set is to be created or already
added entry is added or missing entry is deleted.
-o, -output { plain | save | xml }
Select the output format to the
list
command.
-q, -quiet
Suppress any output to stdout and stderr.
ipset
will still exit with error if it cannot continue.
-r, -resolve
When listing sets, enforce name lookup. The
program will try to display the IP entries resolved to
host names which requires
slow
DNS lookups.
-s, -sorted
Sorted output. When listing or saving sets, the entries are listed sorted.
-n, -name
List just the names of the existing sets, i.e. suppress listing of set headers and members.
-t, -terse
List the set names and headers, i.e. suppress listing of set members.
-f, -file filename
Specify a filename to print into instead of stdout
(list
or
save
commands) or read from instead of stdin
(restore
command).

Summary

IndexedDB can be thought of as a “localStorage on steroids”. It’s a simple key-value database, powerful enough for offline apps, yet simple to use.

The best manual is the specification, the current one is 2.0, but few methods from 3.0 (it’s not much different) are partially supported.

The basic usage can be described with a few phrases:

  1. Get a promise wrapper like idb.
  2. Open a database:
  3. For requests:
    • Create transaction (readwrite if needed).
    • Get the object store .
  4. Then, to search by a key, call methods on the object store directly.
  5. If the data does not fit in memory, use a cursor.

Here’s a small demo app:

Result
index.html

Session state problems in ASP.NET Core 2.1/2.2

To create the ASP.NET Core 2.2 app, I used pretty much the same behaviour, but this time I did not pin the SDK. I have the ASP.NET Core 2.2 SDK installed (2.2.102) so the following generates an ASP.NET Core 2.2 MVC app:

You still need to explicitly install session state, so update as before, by adding to and to .

The newer 2.2 templates have been simplified compared to previous versions, so for consistency I copied across the from the 2.0 app. I also copied across the Index.chtml, About.chtml, and Contact.cshtml view files. Finally, I updated Layout.cshtml to add links for the About and Contact pages in the header.

These two apps, while running different versions of ASP.NET Core, are pretty much the same. Yet this time, if you click around the app, the home page always shows just a single visit to the home page, and doesn’t record any visits to other pages:

Also, if you check your cookies, you’ll find there aren’t any! The cookie is noticeably absent:

Everything is apparently configured correctly, and the session itself appears to be working (as the value set in the action can be successfully retrieved in Index.cshtml). But it seems like session state isn’t being saved between page reloads and navigations.

So why does this happen in ASP.NET Core 2.1 / 2.2 where it worked in ASP.NET Core 2.0?

SYNOPSIS

ipsetOPTIONSCOMMANDCOMMAND-OPTIONS

COMMANDS := { create | add | del | test | destroy | list | save | restore | flush | rename | swap | help | version | }

OPTIONS := { -exist | -output { plain | save | xml } | -quiet | -resolve | -sorted | -name | -terse | -file filename }

ipset create SETNAME TYPENAME [ CREATE-OPTIONS ]

ipset add SETNAME ADD-ENTRY [ ADD-OPTIONS ]

ipset del SETNAME DEL-ENTRY [ DEL-OPTIONS ]

ipset test SETNAME TEST-ENTRY [ TEST-OPTIONS ]

ipset destroy [ SETNAME ]

ipset list [ SETNAME ]

ipset save [ SETNAME ]

ipset restore

ipset flush [ SETNAME ]

ipset rename SETNAME-FROM SETNAME-TO

ipset swap SETNAME-FROM SETNAME-TO

ipset help [ TYPENAME ]

ipset version

ipset
 

Disable optional features

The second option is very similar to the first, in that you keep the existing behaviour in place. The difference is that option 1 treats session state simply as a cache, so you always assume session values can come and go. Option 2 takes a slightly different approach, in that it segments off areas of your application that require session state, and makes them explicitly unavailable until consent is given.

For example, you might require session state to drive a «theme-chooser» that stores whether a user prefers a «light» or «dark» theme. If consent is not given, then you simply hide the «theme-chooser» until they have given consent.

This feels like an improvement over option 1, primarily because of the improved user experience. If you don’t account for features requiring session state, it could be confusing for the user. For example, if you implemented option 1 and so always show the «theme-chooser», the user could keep choosing the dark theme, but it would never remember their choice. That sounds frustrating!

There’s just one big caveat for this approach. Always remember that session state could go away at any moment. You should treat it like a cache, so you shouldn’t build features assuming a) it’ll always be there (even if the user has given consent), or b) that you’ll have one session per real user (different browsers will have different session IDs for the same logical user).

3. Disable the cookie consent requirement

If you’re sure that you don’t need the cookie consent feature, you can easily disable the requirement in your apps. The default template even calls this out explicitly in where you configure the :

The property is a predicate that is called by the framework to check whether non-essential cookies should be written to the response. If the function returns (as above, the default in the template), then non-essential cookies are skipped. Change this to and session state will work without requiring cookies to be explicitly accepted.

4. Mark session cookies as essential

Disabling the cookie consent feature entirely may be a bit heavy handed for your applications. If that’s the case, but you want the session state to be written even before the user accepts cookies, you can mark the session cookie as essential.

There is an overload of that allows you to configure in your file. You can change various settings such as session timeout, and you can also customise the session cookie. To mark the cookie as essential, set to true:

With this approach, the cookie consent banner will still be shown, and non-essential cookies will not be written until it’s clicked. But session state will function immediately, before consent is given, as it’s considered essential:

Как накрутить деньги в игре

Открыв программу, пользователь видит процессы, запущенные на ПК. В списке программ выбирается игра, в которой будут накручиваться деньги. Нажмите кнопку «Открыть» и программа запустит панель для демонстрации файлов выбранной игры.

Мы ввели значение – 20 000. В левой панели программы показаны результаты поиска в папках игровой сессии, содержащих цифровое значение 20 000.

Если искомая цифра часто повторяется в папках, пользователь стоит вернуться в игру и потратить часть денег. Мы потратили 2 500 монет в игре и в графе поиска проставили сумму – 17 500. Программа показала единственный файл, в котором встречается цифровое значение 17 500.

Нажав правой клавишей мыши по строке с цифровым значением 17 500, пользователю открывается панель с выбором действий. Нажав на «Изменить значение у выбранных адресов», пользователь получает окно для изменения цифровых значений.

Чтобы сделать деньги, мы ввели значение – 1 000 000 монет.

Пользователю удалось добавить денег и в игре изменилось количество монет. Иногда, обновленное количество монет появляется после того, как игрок произведет действия персонажем игры (тронется с места, откроет или закроет карту).

Open database

To start working with IndexedDB, we first need to (connect to) a database.

The syntax:

  • – a string, the database name.
  • – a positive integer version, by default (explained below).

We can have many databases with different names, but all of them exist within the current origin (domain/protocol/port). Different websites can’t access each other’s databases.

The call returns object, we should listen to events on it:

  • : database is ready, there’s the “database object” in , we should use it for further calls.
  • : opening failed.
  • : database is ready, but its version is outdated (see below).

IndexedDB has a built-in mechanism of “schema versioning”, absent in server-side databases.

Unlike server-side databases, IndexedDB is client-side, the data is stored in the browser, so we, developers, don’t have full-time access to it. So, when we have published a new version of our app, and the user visits our webpage, we may need to update the database.

If the local database version is less than specified in , then a special event is triggered, and we can compare versions and upgrade data structures as needed.

The event also triggers when the database doesn’t yet exist (technically, its version is ), so we can perform the initialization.

Let’s say we published the first version of our app.

Then we can open the database with version and perform the initialization in an handler like this:

Then, later, we publish the 2nd version.

We can open it with version and perform the upgrade like this:

Please note: as our current version is , the handler has a code branch for version , suitable for users that are accessing for the first time and have no database, and also for version , for upgrades.

And then, only if handler finishes without errors, triggers, and the database is considered successfully opened.

To delete a database:

We can’t open a database using an older open call version

If the current user database has a higher version than in the call, e.g. the existing DB version is , and we try to , then that’s an error, triggers.

That’s rare, but such a thing may happen when a visitor loads outdated JavaScript code, e.g. from a proxy cache. So the code is old, but his database is new.

To protect from errors, we should check and suggest a page reload. Use proper HTTP caching headers to avoid loading the old code, so that you’ll never have such problems.

As we’re talking about versioning, let’s tackle a small related problem.

Let’s say:

  1. A visitor opened our site in a browser tab, with database version .
  2. Then we rolled out an update, so our code is newer.
  3. And then the same visitor opens our site in another tab.

So there’s a tab with an open connection to DB version , while the second one attempts to update it to version in its handler.

The problem is that a database is shared between two tabs, as it’s the same site, same origin. And it can’t be both version and . To perform the update to version , all connections to version 1 must be closed, including the one in the first tab.

In order to organize that, the event triggers on the “outdated” database object. We should listen for it and close the old database connection (and probably suggest a page reload, to load the updated code).

If we don’t listen for the event and don’t close the old connection, then the second, new connection won’t be made. The object will emit the event instead of . So the second tab won’t work.

Here’s the code to correctly handle the parallel upgrade. It installs the handler, that triggers if the current database connection becomes outdated (db version is updated elsewhere) and closes the connection.

…In other words, here we do two things:

  1. The listener informs us about a parallel update attempt, if the current database version becomes outdated.
  2. The listener informs us about the opposite situation: there’s a connection to an outdated version elsewhere, and it doesn’t close, so the newer connection can’t be made.

We can handle things more gracefully in , prompt the visitor to save the data before the connection is closed and so on.

Or, an alternative approach would be to not close the database in , but instead use the handler (in the new tab) to alert the visitor, tell him that the newer version can’t be loaded until they close other tabs.

These update collisions happen rarely, but we should at least have some handling for them, at least an handler, to prevent our script from dying silently.

# Stuck on [EB|#LOG:EXITBS:START]

This section will be split into 3 parts, so pay close attention:

Booter Issues

The main culprits to watch for in the Booter section are:

  • DevirtualiseMmio

    • Certain MMIO spaces are still required to function correctly, so you’ll need to either exclude these regions in Booter -> MmioWhitelist or disable this quirk outright. More info here:
    • For TRx40 users, enable this quirk
    • For X99 users, disable this quirk as it breaks with some firmwares
  • SetupVirtualMap

    • This quirk is required for the majority of firmwares and without it it’s very common to kernel panic here, so enable it if not already
      • Mainly Z390 and older require this quirk enabled
      • However, certain firmwares(mainly 2020+) do not work with this quirk and so may actually cause this kernel panic:
        • Intel’s Ice Lake series
        • Intel’s Comet Lake series(B460, H470, Z490, etc)
        • AMD’s B550 and A520(Latest BIOS on X570 are also included now)
        • AMD’s TRx40
        • VMs like QEMU
        • X299 2020+ BIOS updates(This applies to other X299 boards on the latest BIOS that released either in late 2019 or 2020+)
  • EnableWriteUnprotector

    • Another issue may be that macOS is conflicting with the write protection from CR0 register, to resolve this we have 2 options:
      • If your firmware supports MATs(2018+ firmwares):
        • EnableWriteUnprotector -> False
        • RebuildAppleMemoryMap -> True
        • SyncRuntimePermissions -> True
      • For older firmwares:
        • EnableWriteUnprotector -> True
        • RebuildAppleMemoryMap -> False
        • SyncRuntimePermissions -> False
      • Note: Some laptops(ex. Dell Inspiron 5370) even with MATs support will halt on boot up, in these cases you’ll have two options:
        • Boot with the old firmware quirk combo(ie. With EnableWriteUnprotector and disable + )
        • Enable and follow MmioWhitelist guide(opens new window)

Regarding MATs support, firmwares built against EDK 2018 will support this and many OEMs have even added support all the way back to Skylake laptops. Issue is it’s not always obvious if an OEM has updated the firmware, you can check the OpenCore logs whether yours supports it(See here how to get a log):

Note: 1 means it supports MATs, while 0 means it does not.

Kernel Patch Issues

This section will be split between Intel and AMD users:

AMD Users

  • Missing kernel patches(opens new window)(only applies for AMD CPUs, make sure they’re OpenCore patches and not Clover. Clover uses while OpenCore has and )

Intel Users

  • AppleXcpmCfgLock and AppleCpuPmCfgLock
    • Missing CFG or XCPM patches, please enable and
      • Haswell and newer only need AppleXcpmCfgLock
      • Ivy Bridge and older only need AppleCpuPmCfgLock
    • Alternatively you can properly disable CFG-Lock: Fixing CFG Lock(opens new window)
  • AppleXcpmExtraMsrs

    May also be required, this is generally meant for Pentiums, HEDT and other odd systems not natively supported in macOS.

Legacy Intel users

For macOS Big Sur, many firmwares have issues determining the CPU core count and thus will kernel panic too early for screen printing. Via serial, you can see the following panic:

To resolve:

  • Enable under Booter -> Quirks

However on certain machines like the HP Compaq DC 7900, the firmware will still panic so we need to force a CPU core count value. Only use the below patch if AvoidRuntimeDefrag didn’t work:

Legacy CPU Core patch

To do this, Add the following patch(replacing the 04 from B8 04 00 00 00 C3 with the amount of CPU threads your hardware supports):

Key Type Value
Base String _acpi_count_enabled_logical_processors
Count Integer 1
Enabled Boolean True
Find Data
Identifier String Kernel
Limit Integer
Mask Data
MaxKernel String
MinKernel String 20.0.0
Replace Data
ReplaceMask Data
Skip Integer
  • ProvideConsoleGop
    • Needed for transitioning to the next screen, this was originally part of AptioMemoryFix but is now within OpenCore as this quirk. Can be found under UEFI -> Output
    • Note as of 0.5.6, this quirk is enabled by default in the sample.plist
  • IgnoreInvalidFlexRatio

    This is needed for Broadwell and older. Not for AMD and Skylake or newer

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Клуб GTA
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: